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
This commit is contained in:
parent
91a2e55166
commit
95a6889312
@ -27,6 +27,7 @@ namespace android {
|
|||||||
|
|
||||||
// OBB flags (bit 0)
|
// OBB flags (bit 0)
|
||||||
#define OBB_OVERLAY (1 << 0)
|
#define OBB_OVERLAY (1 << 0)
|
||||||
|
#define OBB_SALTED (1 << 1)
|
||||||
|
|
||||||
class ObbFile : public RefBase {
|
class ObbFile : public RefBase {
|
||||||
protected:
|
protected:
|
||||||
@ -70,6 +71,26 @@ public:
|
|||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unsigned char* getSalt(size_t* length) const {
|
||||||
|
if ((mFlags & OBB_SALTED) == 0) {
|
||||||
|
*length = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = sizeof(mSalt);
|
||||||
|
return mSalt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setSalt(const unsigned char* salt, size_t length) {
|
||||||
|
if (length != sizeof(mSalt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mSalt, salt, sizeof(mSalt));
|
||||||
|
mFlags |= OBB_SALTED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool isOverlay() {
|
bool isOverlay() {
|
||||||
return (mFlags & OBB_OVERLAY) == OBB_OVERLAY;
|
return (mFlags & OBB_OVERLAY) == OBB_OVERLAY;
|
||||||
}
|
}
|
||||||
@ -103,6 +124,12 @@ private:
|
|||||||
/* Flags for this OBB type. */
|
/* Flags for this OBB type. */
|
||||||
int32_t mFlags;
|
int32_t mFlags;
|
||||||
|
|
||||||
|
/* Whether the file is salted. */
|
||||||
|
bool mSalted;
|
||||||
|
|
||||||
|
/* The encryption salt. */
|
||||||
|
unsigned char mSalt[8];
|
||||||
|
|
||||||
const char* mFileName;
|
const char* mFileName;
|
||||||
|
|
||||||
size_t mFileSize;
|
size_t mFileSize;
|
||||||
|
@ -29,10 +29,11 @@
|
|||||||
|
|
||||||
#define kFooterTagSize 8 /* last two 32-bit integers */
|
#define kFooterTagSize 8 /* last two 32-bit integers */
|
||||||
|
|
||||||
#define kFooterMinSize 25 /* 32-bit signature version (4 bytes)
|
#define kFooterMinSize 33 /* 32-bit signature version (4 bytes)
|
||||||
* 32-bit package version (4 bytes)
|
* 32-bit package version (4 bytes)
|
||||||
* 32-bit flags (4 bytes)
|
* 32-bit flags (4 bytes)
|
||||||
* 32-bit package name size (4-bytes)
|
* 64-bit salt (8 bytes)
|
||||||
|
* 32-bit package name size (4 bytes)
|
||||||
* >=1-character package name (1 byte)
|
* >=1-character package name (1 byte)
|
||||||
* 32-bit footer size (4 bytes)
|
* 32-bit footer size (4 bytes)
|
||||||
* 32-bit footer marker (4 bytes)
|
* 32-bit footer marker (4 bytes)
|
||||||
@ -47,8 +48,9 @@
|
|||||||
/* offsets in version 1 of the header */
|
/* offsets in version 1 of the header */
|
||||||
#define kPackageVersionOffset 4
|
#define kPackageVersionOffset 4
|
||||||
#define kFlagsOffset 8
|
#define kFlagsOffset 8
|
||||||
#define kPackageNameLenOffset 12
|
#define kSaltOffset 12
|
||||||
#define kPackageNameOffset 16
|
#define kPackageNameLenOffset 20
|
||||||
|
#define kPackageNameOffset 24
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
|
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
|
||||||
@ -79,11 +81,12 @@ typedef off64_t my_off64_t;
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
ObbFile::ObbFile() :
|
ObbFile::ObbFile()
|
||||||
mPackageName(""),
|
: mPackageName("")
|
||||||
mVersion(-1),
|
, mVersion(-1)
|
||||||
mFlags(0)
|
, mFlags(0)
|
||||||
{
|
{
|
||||||
|
memset(mSalt, 0, sizeof(mSalt));
|
||||||
}
|
}
|
||||||
|
|
||||||
ObbFile::~ObbFile() {
|
ObbFile::~ObbFile() {
|
||||||
@ -192,7 +195,7 @@ bool ObbFile::parseObbFile(int fd)
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (int i = 0; i < footerSize; ++i) {
|
for (int i = 0; i < footerSize; ++i) {
|
||||||
LOGI("char: 0x%02x", scanBuf[i]);
|
LOGI("char: 0x%02x\n", scanBuf[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -206,6 +209,8 @@ bool ObbFile::parseObbFile(int fd)
|
|||||||
mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
|
mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
|
||||||
mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset);
|
mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset);
|
||||||
|
|
||||||
|
memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt));
|
||||||
|
|
||||||
uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
|
uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
|
||||||
if (packageNameLen <= 0
|
if (packageNameLen <= 0
|
||||||
|| packageNameLen > (footerSize - kPackageNameOffset)) {
|
|| packageNameLen > (footerSize - kPackageNameOffset)) {
|
||||||
@ -255,7 +260,7 @@ bool ObbFile::writeTo(int fd)
|
|||||||
my_lseek64(fd, 0, SEEK_END);
|
my_lseek64(fd, 0, SEEK_END);
|
||||||
|
|
||||||
if (mPackageName.size() == 0 || mVersion == -1) {
|
if (mPackageName.size() == 0 || mVersion == -1) {
|
||||||
LOGW("tried to write uninitialized ObbFile data");
|
LOGW("tried to write uninitialized ObbFile data\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,43 +269,48 @@ bool ObbFile::writeTo(int fd)
|
|||||||
|
|
||||||
put4LE(intBuf, kSigVersion);
|
put4LE(intBuf, kSigVersion);
|
||||||
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
||||||
LOGW("couldn't write signature version: %s", strerror(errno));
|
LOGW("couldn't write signature version: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
put4LE(intBuf, mVersion);
|
put4LE(intBuf, mVersion);
|
||||||
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
||||||
LOGW("couldn't write package version");
|
LOGW("couldn't write package version\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
put4LE(intBuf, mFlags);
|
put4LE(intBuf, mFlags);
|
||||||
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
||||||
LOGW("couldn't write package version");
|
LOGW("couldn't write package version\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fd, mSalt, sizeof(mSalt)) != (ssize_t)sizeof(mSalt)) {
|
||||||
|
LOGW("couldn't write salt: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t packageNameLen = mPackageName.size();
|
size_t packageNameLen = mPackageName.size();
|
||||||
put4LE(intBuf, packageNameLen);
|
put4LE(intBuf, packageNameLen);
|
||||||
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
||||||
LOGW("couldn't write package name length: %s", strerror(errno));
|
LOGW("couldn't write package name length: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) {
|
if (write(fd, mPackageName.string(), packageNameLen) != (ssize_t)packageNameLen) {
|
||||||
LOGW("couldn't write package name: %s", strerror(errno));
|
LOGW("couldn't write package name: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
put4LE(intBuf, kPackageNameOffset + packageNameLen);
|
put4LE(intBuf, kPackageNameOffset + packageNameLen);
|
||||||
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
||||||
LOGW("couldn't write footer size: %s", strerror(errno));
|
LOGW("couldn't write footer size: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
put4LE(intBuf, kSignature);
|
put4LE(intBuf, kSignature);
|
||||||
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
|
||||||
LOGW("couldn't write footer magic signature: %s", strerror(errno));
|
LOGW("couldn't write footer magic signature: %s\n", strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@ -63,6 +64,10 @@ TEST_F(ObbFileTest, WriteThenRead) {
|
|||||||
|
|
||||||
mObbFile->setPackageName(String8(packageName));
|
mObbFile->setPackageName(String8(packageName));
|
||||||
mObbFile->setVersion(versionNum);
|
mObbFile->setVersion(versionNum);
|
||||||
|
#define SALT_SIZE 8
|
||||||
|
unsigned char salt[SALT_SIZE] = {0x01, 0x10, 0x55, 0xAA, 0xFF, 0x00, 0x5A, 0xA5};
|
||||||
|
EXPECT_TRUE(mObbFile->setSalt(salt, SALT_SIZE))
|
||||||
|
<< "Salt should be successfully set";
|
||||||
|
|
||||||
EXPECT_TRUE(mObbFile->writeTo(mFileName))
|
EXPECT_TRUE(mObbFile->writeTo(mFileName))
|
||||||
<< "couldn't write to fake .obb file";
|
<< "couldn't write to fake .obb file";
|
||||||
@ -77,6 +82,19 @@ TEST_F(ObbFileTest, WriteThenRead) {
|
|||||||
const char* currentPackageName = mObbFile->getPackageName().string();
|
const char* currentPackageName = mObbFile->getPackageName().string();
|
||||||
EXPECT_STREQ(packageName, currentPackageName)
|
EXPECT_STREQ(packageName, currentPackageName)
|
||||||
<< "package name didn't come out the same as it went in";
|
<< "package name didn't come out the same as it went in";
|
||||||
|
|
||||||
|
size_t saltLen;
|
||||||
|
const unsigned char* newSalt = mObbFile->getSalt(&saltLen);
|
||||||
|
|
||||||
|
EXPECT_EQ(sizeof(salt), saltLen)
|
||||||
|
<< "salt sizes were not the same";
|
||||||
|
|
||||||
|
for (int i = 0; i < sizeof(salt); i++) {
|
||||||
|
EXPECT_EQ(salt[i], newSalt[i])
|
||||||
|
<< "salt character " << i << " should be equal";
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(memcmp(newSalt, salt, sizeof(salt)) == 0)
|
||||||
|
<< "salts should be the same";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user