2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <androidfw/ObbFile.h>
18 #include <utils/String8.h>
25 using namespace android;
27 static const char* gProgName = "obbtool";
28 static const char* gProgVersion = "1.0";
30 static int wantUsage = 0;
31 static int wantVersion = 0;
35 #define ADD_OPTS "n:v:os:"
36 static const struct option longopts[] = {
37 {"help", no_argument, &wantUsage, 1},
38 {"version", no_argument, &wantVersion, 1},
41 {"name", required_argument, NULL, 'n'},
42 {"version", required_argument, NULL, 'v'},
43 {"overlay", optional_argument, NULL, 'o'},
44 {"salt", required_argument, NULL, 's'},
57 memset(&salt, 0, sizeof(salt));
64 unsigned char salt[SALT_LEN];
72 fprintf(stderr, "Opaque Binary Blob (OBB) Tool\n\n");
73 fprintf(stderr, "Usage:\n");
75 " %s a[dd] [ OPTIONS ] FILENAME\n"
76 " Adds an OBB signature to the file.\n\n", gProgName);
79 " -n <package name> sets the OBB package name (required)\n"
80 " -v <OBB version> sets the OBB version (required)\n"
81 " -o sets the OBB overlay flag\n"
82 " -s <8 byte hex salt> sets the crypto key salt (if encrypted)\n"
85 " %s r[emove] FILENAME\n"
86 " Removes the OBB signature from the file.\n\n", gProgName);
88 " %s i[nfo] FILENAME\n"
89 " Prints the OBB signature information of a file.\n\n", gProgName);
92 void doAdd(const char* filename, PackageInfo* info) {
93 ObbFile *obb = new ObbFile();
94 if (obb->readFrom(filename)) {
95 fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename);
99 obb->setPackageName(String8(info->packageName));
100 obb->setVersion(info->packageVersion);
101 obb->setOverlay(info->overlay);
103 obb->setSalt(info->salt, SALT_LEN);
106 if (!obb->writeTo(filename)) {
107 fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n",
108 filename, strerror(errno));
112 fprintf(stderr, "OBB signature successfully written\n");
115 void doRemove(const char* filename) {
116 ObbFile *obb = new ObbFile();
117 if (!obb->readFrom(filename)) {
118 fprintf(stderr, "ERROR: %s: no OBB signature present\n", filename);
122 if (!obb->removeFrom(filename)) {
123 fprintf(stderr, "ERROR: %s: couldn't remove OBB signature\n", filename);
127 fprintf(stderr, "OBB signature successfully removed\n");
130 void doInfo(const char* filename) {
131 ObbFile *obb = new ObbFile();
132 if (!obb->readFrom(filename)) {
133 fprintf(stderr, "ERROR: %s: couldn't read OBB signature\n", filename);
137 printf("OBB info for '%s':\n", filename);
138 printf("Package name: %s\n", obb->getPackageName().string());
139 printf(" Version: %d\n", obb->getVersion());
140 printf(" Flags: 0x%08x\n", obb->getFlags());
141 printf(" Overlay: %s\n", obb->isOverlay() ? "true" : "false");
145 const unsigned char* salt = obb->getSalt(&saltLen);
147 for (int i = 0; i < SALT_LEN; i++) {
148 printf("%02x", salt[i]);
156 bool fromHex(char h, unsigned char *b) {
157 if (h >= '0' && h <= '9') {
160 } else if (h >= 'a' && h <= 'f') {
163 } else if (h >= 'A' && h <= 'F') {
170 bool hexToByte(char h1, char h2, unsigned char* b) {
171 unsigned char first, second;
172 if (!fromHex(h1, &first)) return false;
173 if (!fromHex(h2, &second)) return false;
174 *b = (first << 4) | second;
181 int main(int argc, char* const argv[])
184 int option_index = 0;
185 PackageInfo package_info;
187 int result = 1; // pessimistically assume an error.
194 while ((opt = getopt_long(argc, argv, ADD_OPTS, longopts, &option_index)) != -1) {
197 if (longopts[option_index].flag)
199 fprintf(stderr, "'%s' requires an argument\n", longopts[option_index].name);
203 package_info.packageName = optarg;
207 package_info.packageVersion = strtol(optarg, &end, 10);
208 if (*optarg == '\0' || *end != '\0') {
209 fprintf(stderr, "ERROR: invalid version; should be integer!\n\n");
216 package_info.overlay = true;
219 if (strlen(optarg) != SALT_LEN * 2) {
220 fprintf(stderr, "ERROR: salt must be 8 bytes in hex (e.g., ABCD65031337D00D)\n\n");
225 package_info.salted = true;
228 for (int i = 0, j = 0; i < SALT_LEN; i++, j+=2) {
229 if (!hexToByte(optarg[j], optarg[j+1], &b)) {
230 fprintf(stderr, "ERROR: salt must be in hex (e.g., ABCD65031337D00D)\n");
234 package_info.salt[i] = b;
244 fprintf(stderr, "%s %s\n", gProgName, gProgVersion);
251 #define CHECK_OP(name) \
252 if (strncmp(op, name, opsize)) { \
253 fprintf(stderr, "ERROR: unknown function '%s'!\n\n", op); \
259 const char* op = argv[optind++];
260 const int opsize = strlen(op);
262 if (optind >= argc) {
263 fprintf(stderr, "ERROR: filename required!\n\n");
268 const char* filename = argv[optind++];
273 if (package_info.packageName == NULL) {
274 fprintf(stderr, "ERROR: arguments required 'packageName' and 'version'\n");
277 doAdd(filename, &package_info);
288 fprintf(stderr, "ERROR: unknown command '%s'!\n\n", op);