Commit fefe5915 authored by Ethan Yonker's avatar Ethan Yonker
Browse files

FBE for Pixel 2

Includes various minor fixes for building in Android 8 trees with r23+ tag

Update FBE extended header in libtar to version 2 and include the entire
ext4_encryption_policy structure now after translating the policy.

See this post for more details:
https://plus.google.com/u/1/+DeesTroy/posts/i33ygUi7tiu

Change-Id: I2af981e51f459b17fcd895fb8c2d3f6c8200e24b
parent dc864ec8
......@@ -64,9 +64,48 @@ static void set_usb_driver(bool enabled) {
}
}
// On Android 8.0 for some reason init can't seem to completely stop adbd
// so we have to kill it too if it doesn't die on its own.
static void kill_adbd() {
DIR* dir = opendir("/proc");
if (dir) {
struct dirent* de = 0;
while ((de = readdir(dir)) != 0) {
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
continue;
int pid = -1;
int ret = sscanf(de->d_name, "%d", &pid);
if (ret == 1) {
char cmdpath[PATH_MAX];
sprintf(cmdpath, "/proc/%d/cmdline", pid);
FILE* file = fopen(cmdpath, "r");
size_t task_size = PATH_MAX;
char task[PATH_MAX];
char* p = task;
if (getline(&p, &task_size, file) > 0) {
if (strstr(task, "adbd") != 0) {
printf("adbd pid %d found, sending kill.\n", pid);
kill(pid, SIGINT);
usleep(5000);
kill(pid, SIGKILL);
}
}
fclose(file);
}
}
closedir(dir);
}
}
static void stop_adbd() {
printf("Stopping adbd...\n");
property_set("ctl.stop", "adbd");
usleep(5000);
kill_adbd();
set_usb_driver(false);
}
......
......@@ -30,6 +30,7 @@
#include <vector>
#include <fstream>
#include <sstream>
#include <assert.h>
#include "twadbstream.h"
#include "libtwadbbu.hpp"
......@@ -50,8 +51,8 @@ bool twadbbu::Check_ADB_Backup_File(std::string fname) {
bytes = read(fd, &buf, sizeof(buf));
close(fd);
if (memcpy(&adbbuhdr, buf, sizeof(adbbuhdr)) < 0) {
printf("Unable to memcpy: %s.\n", fname.c_str(), strerror(errno));
if (memcpy(&adbbuhdr, buf, sizeof(adbbuhdr)) == NULL) {
printf("Unable to memcpy: %s (%s).\n", fname.c_str(), strerror(errno));
return false;
}
adbbuhdrcrc = adbbuhdr.crc;
......@@ -77,7 +78,7 @@ std::vector<std::string> twadbbu::Get_ADB_Backup_Files(std::string fname) {
while (1) {
std::string cmdstr;
int readbytes;
if (readbytes = read(fd, &buf, sizeof(buf)) > 0) {
if ((readbytes = read(fd, &buf, sizeof(buf))) > 0) {
memcpy(&structcmd, buf, sizeof(structcmd));
assert(structcmd.type == TWENDADB || structcmd.type == TWIMG || structcmd.type == TWFN);
cmdstr = structcmd.type;
......
......@@ -5,7 +5,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libe4crypt
LOCAL_MODULE_TAGS := eng optional
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := Decrypt.cpp Ext4Crypt.cpp Keymaster.cpp KeyStorage.cpp ScryptParameters.cpp Utils.cpp HashPassword.cpp ext4_crypt.cpp
LOCAL_SRC_FILES := Decrypt.cpp Ext4Crypt.cpp ScryptParameters.cpp Utils.cpp HashPassword.cpp ext4_crypt.cpp
LOCAL_SHARED_LIBRARIES := libselinux libc libc++ libext4_utils libsoftkeymaster libbase libcrypto libcutils libkeymaster_messages libhardware libprotobuf-cpp-lite
LOCAL_STATIC_LIBRARIES := libscrypt_static
LOCAL_C_INCLUDES := system/extras/ext4_utils system/extras/ext4_utils/include/ext4_utils external/scrypt/lib/crypto system/security/keystore hardware/libhardware/include/hardware system/security/softkeymaster/include/keymaster system/keymaster/include
......@@ -14,6 +14,16 @@ ifneq ($(wildcard hardware/libhardware/include/hardware/keymaster0.h),)
LOCAL_CFLAGS += -DTW_CRYPTO_HAVE_KEYMASTERX
LOCAL_C_INCLUDES += external/boringssl/src/include
endif
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0)
LOCAL_CFLAGS += -DUSE_KEYSTORAGE_3 -DHAVE_LIBKEYUTILS -DHAVE_SYNTH_PWD_SUPPORT -DHAVE_GATEKEEPER1
LOCAL_SRC_FILES += Keymaster3.cpp KeyStorage3.cpp
LOCAL_SHARED_LIBRARIES += android.hardware.keymaster@3.0 libkeystore_binder libhidlbase libutils libkeyutils libbinder
LOCAL_SHARED_LIBRARIES += android.hardware.gatekeeper@1.0
LOCAL_SRC_FILES += Weaver1.cpp
LOCAL_SHARED_LIBRARIES += android.hardware.weaver@1.0
else
LOCAL_SRC_FILES += Keymaster.cpp KeyStorage.cpp
endif
include $(BUILD_SHARED_LIBRARY)
......
This diff is collapsed.
......@@ -41,8 +41,16 @@
#include <private/android_filesystem_config.h>
#ifdef HAVE_SYNTH_PWD_SUPPORT
#include <ext4_utils/ext4_crypt.h>
#else
#include "ext4_crypt.h"
#endif
#ifndef HAVE_LIBKEYUTILS
#include "key_control.h"
#else
#include <keyutils.h>
#endif
#include <hardware/gatekeeper.h>
#include "HashPassword.h"
......
......@@ -28,16 +28,37 @@
#include <stdlib.h>
#include <openssl/sha.h>
#include "HashPassword.h"
#define PASS_PADDING_SIZE 128
#define SHA512_HEX_SIZE SHA512_DIGEST_LENGTH * 2
std::string HashPassword(const std::string& Password) {
size_t size = PASS_PADDING_SIZE + Password.size();
void* PersonalizedHashBinary(const char* prefix, const char* key, const size_t key_size) {
size_t size = PASS_PADDING_SIZE + key_size;
unsigned char* buffer = (unsigned char*)calloc(1, size);
if (!buffer) return NULL; // failed to malloc
memcpy((void*)buffer, (void*)prefix, strlen(prefix));
unsigned char* ptr = buffer + PASS_PADDING_SIZE;
memcpy((void*)ptr, key, key_size);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512_CTX sha512;
SHA512_Init(&sha512);
SHA512_Update(&sha512, buffer, size);
SHA512_Final(hash, &sha512);
free(buffer);
void* ret = malloc(SHA512_DIGEST_LENGTH);
if (!ret) return NULL; // failed to malloc
memcpy(ret, (void*)&hash[0], SHA512_DIGEST_LENGTH);
return ret;
}
std::string PersonalizedHash(const char* prefix, const char* key, const size_t key_size) {
size_t size = PASS_PADDING_SIZE + key_size;
unsigned char* buffer = (unsigned char*)calloc(1, size);
const char* prefix = "Android FBE credential hash";
if (!buffer) return ""; // failed to malloc
memcpy((void*)buffer, (void*)prefix, strlen(prefix));
unsigned char* ptr = buffer + PASS_PADDING_SIZE;
memcpy((void*)ptr, Password.c_str(), Password.size());
memcpy((void*)ptr, key, key_size);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512_CTX sha512;
SHA512_Init(&sha512);
......@@ -49,5 +70,15 @@ std::string HashPassword(const std::string& Password) {
sprintf(hex_hash + (index * 2), "%02X", hash[index]);
hex_hash[128] = 0;
std::string ret = hex_hash;
free(buffer);
return ret;
}
std::string PersonalizedHash(const char* prefix, const std::string& Password) {
return PersonalizedHash(prefix, Password.c_str(), Password.size());
}
std::string HashPassword(const std::string& Password) {
const char* prefix = FBE_PERSONALIZATION;
return PersonalizedHash(prefix, Password);
}
......@@ -19,6 +19,16 @@
#include <string>
#define FBE_PERSONALIZATION "Android FBE credential hash"
#define PERSONALISATION_WEAVER_KEY "weaver-key"
#define PERSONALISATION_WEAVER_PASSWORD "weaver-pwd"
#define PERSONALISATION_APPLICATION_ID "application-id"
#define PERSONALIZATION_FBE_KEY "fbe-key"
void* PersonalizedHashBinary(const char* prefix, const char* key, const size_t key_size);
std::string PersonalizedHash(const char* prefix, const char* key, const size_t key_size);
std::string PersonalizedHash(const char* prefix, const std::string& Password);
std::string HashPassword(const std::string& Password);
#endif
This diff is collapsed.
/*
* Copyright (C) 2016 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.
*/
#ifndef ANDROID_VOLD_KEYSTORAGE_H
#define ANDROID_VOLD_KEYSTORAGE_H
#include <string>
namespace android {
namespace vold {
// Represents the information needed to decrypt a disk encryption key.
// If "token" is nonempty, it is passed in as a required Gatekeeper auth token.
// If "token" and "secret" are nonempty, "secret" is appended to the application-specific
// binary needed to unlock.
// If only "secret" is nonempty, it is used to decrypt in a non-Keymaster process.
class KeyAuthentication {
public:
KeyAuthentication(std::string t, std::string s) : token{t}, secret{s} {};
bool usesKeymaster() const { return !token.empty() || secret.empty(); };
const std::string token;
const std::string secret;
};
extern const KeyAuthentication kEmptyAuthentication;
// Create a directory at the named path, and store "key" in it,
// in such a way that it can only be retrieved via Keymaster and
// can be securely deleted.
// It's safe to move/rename the directory after creation.
bool storeKey(const std::string& dir, const KeyAuthentication& auth, const std::string& key);
// Retrieve the key from the named directory.
bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, std::string* key);
// Securely destroy the key stored in the named directory and delete the directory.
bool destroyKey(const std::string& dir);
bool runSecdiscardSingle(const std::string& file);
} // namespace vold
} // namespace android
#endif
/*
* Copyright (C) 2016 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 "Keymaster3.h"
//#include <android-base/logging.h>
#include <keystore/keymaster_tags.h>
#include <keystore/authorization_set.h>
#include <keystore/keystore_hidl_support.h>
#include <iostream>
#define ERROR 1
#define LOG(x) std::cout
using namespace ::keystore;
using android::hardware::hidl_string;
namespace android {
namespace vold {
KeymasterOperation::~KeymasterOperation() {
if (mDevice.get()) mDevice->abort(mOpHandle);
}
bool KeymasterOperation::updateCompletely(const std::string& input, std::string* output) {
if (output)
output->clear();
auto it = input.begin();
uint32_t inputConsumed;
ErrorCode km_error;
auto hidlCB = [&] (ErrorCode ret, uint32_t _inputConsumed,
const hidl_vec<KeyParameter>& /*ignored*/, const hidl_vec<uint8_t>& _output) {
km_error = ret;
if (km_error != ErrorCode::OK) return;
inputConsumed = _inputConsumed;
if (output)
output->append(reinterpret_cast<const char*>(&_output[0]), _output.size());
};
while (it != input.end()) {
size_t toRead = static_cast<size_t>(input.end() - it);
auto inputBlob = blob2hidlVec(reinterpret_cast<const uint8_t*>(&*it), toRead);
auto error = mDevice->update(mOpHandle, hidl_vec<KeyParameter>(), inputBlob, hidlCB);
if (!error.isOk()) {
LOG(ERROR) << "update failed: " << error.description();
mDevice = nullptr;
return false;
}
if (km_error != ErrorCode::OK) {
LOG(ERROR) << "update failed, code " << int32_t(km_error);
mDevice = nullptr;
return false;
}
if (inputConsumed > toRead) {
LOG(ERROR) << "update reported too much input consumed";
mDevice = nullptr;
return false;
}
it += inputConsumed;
}
return true;
}
bool KeymasterOperation::finish(std::string* output) {
ErrorCode km_error;
auto hidlCb = [&] (ErrorCode ret, const hidl_vec<KeyParameter>& /*ignored*/,
const hidl_vec<uint8_t>& _output) {
km_error = ret;
if (km_error != ErrorCode::OK) return;
if (output)
output->assign(reinterpret_cast<const char*>(&_output[0]), _output.size());
};
auto error = mDevice->finish(mOpHandle, hidl_vec<KeyParameter>(), hidl_vec<uint8_t>(),
hidl_vec<uint8_t>(), hidlCb);
mDevice = nullptr;
if (!error.isOk()) {
LOG(ERROR) << "finish failed: " << error.description();
return false;
}
if (km_error != ErrorCode::OK) {
LOG(ERROR) << "finish failed, code " << int32_t(km_error);
return false;
}
return true;
}
Keymaster::Keymaster() {
mDevice = ::android::hardware::keymaster::V3_0::IKeymasterDevice::getService();
}
/*bool Keymaster::generateKey(const AuthorizationSet& inParams, std::string* key) {
ErrorCode km_error;
auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& keyBlob,
const KeyCharacteristics& /*ignored* /) {
km_error = ret;
if (km_error != ErrorCode::OK) return;
if (key)
key->assign(reinterpret_cast<const char*>(&keyBlob[0]), keyBlob.size());
};
auto error = mDevice->generateKey(inParams.hidl_data(), hidlCb);
if (!error.isOk()) {
LOG(ERROR) << "generate_key failed: " << error.description();
return false;
}
if (km_error != ErrorCode::OK) {
LOG(ERROR) << "generate_key failed, code " << int32_t(km_error);
return false;
}
return true;
}*/
bool Keymaster::deleteKey(const std::string& key) {
LOG(ERROR) << "NOT deleting key in TWRP";
return false;
/*auto keyBlob = blob2hidlVec(key);
auto error = mDevice->deleteKey(keyBlob);
if (!error.isOk()) {
LOG(ERROR) << "delete_key failed: " << error.description();
return false;
}
if (ErrorCode(error) != ErrorCode::OK) {
LOG(ERROR) << "delete_key failed, code " << uint32_t(ErrorCode(error));
return false;
}
return true;*/
}
bool Keymaster::upgradeKey(const std::string& oldKey, const AuthorizationSet& inParams,
std::string* newKey) {
auto oldKeyBlob = blob2hidlVec(oldKey);
ErrorCode km_error;
auto hidlCb = [&] (ErrorCode ret, const hidl_vec<uint8_t>& upgradedKeyBlob) {
km_error = ret;
if (km_error != ErrorCode::OK) return;
if (newKey)
newKey->assign(reinterpret_cast<const char*>(&upgradedKeyBlob[0]),
upgradedKeyBlob.size());
};
auto error = mDevice->upgradeKey(oldKeyBlob, inParams.hidl_data(), hidlCb);
if (!error.isOk()) {
LOG(ERROR) << "upgrade_key failed: " << error.description();
return false;
}
if (km_error != ErrorCode::OK) {
LOG(ERROR) << "upgrade_key failed, code " << int32_t(km_error);
return false;
}
return true;
}
KeymasterOperation Keymaster::begin(KeyPurpose purpose, const std::string& key,
const AuthorizationSet& inParams,
AuthorizationSet* outParams) {
auto keyBlob = blob2hidlVec(key);
uint64_t mOpHandle;
ErrorCode km_error;
auto hidlCb = [&] (ErrorCode ret, const hidl_vec<KeyParameter>& _outParams,
uint64_t operationHandle) {
km_error = ret;
if (km_error != ErrorCode::OK) return;
if (outParams)
*outParams = _outParams;
mOpHandle = operationHandle;
};
auto error = mDevice->begin(purpose, keyBlob, inParams.hidl_data(), hidlCb);
if (!error.isOk()) {
LOG(ERROR) << "begin failed: " << error.description();
return KeymasterOperation(ErrorCode::UNKNOWN_ERROR);
}
if (km_error != ErrorCode::OK) {
LOG(ERROR) << "begin failed, code " << int32_t(km_error);
return KeymasterOperation(km_error);
}
return KeymasterOperation(mDevice, mOpHandle);
}
bool Keymaster::isSecure() {
bool _isSecure = false;
auto rc = mDevice->getHardwareFeatures(
[&] (bool isSecure, bool, bool, bool, bool, const hidl_string&, const hidl_string&) {
_isSecure = isSecure; });
return rc.isOk() && _isSecure;
}
} // namespace vold
} // namespace android
using namespace ::android::vold;
int keymaster_compatibility_cryptfs_scrypt() {
Keymaster dev;
if (!dev) {
LOG(ERROR) << "Failed to initiate keymaster session";
return -1;
}
return dev.isSecure();
}
/*int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size,
uint64_t rsa_exponent,
uint32_t ratelimit,
uint8_t* key_buffer,
uint32_t key_buffer_size,
uint32_t* key_out_size)
{
Keymaster dev;
std::string key;
if (!dev) {
LOG(ERROR) << "Failed to initiate keymaster session";
return -1;
}
if (!key_buffer || !key_out_size) {
LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument";
return -1;
}
if (key_out_size) {
*key_out_size = 0;
}
auto paramBuilder = AuthorizationSetBuilder()
.Authorization(TAG_ALGORITHM, Algorithm::RSA)
.Authorization(TAG_KEY_SIZE, rsa_key_size)
.Authorization(TAG_RSA_PUBLIC_EXPONENT, rsa_exponent)
.Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
.Authorization(TAG_PADDING, PaddingMode::NONE)
.Authorization(TAG_DIGEST, Digest::NONE)
.Authorization(TAG_BLOB_USAGE_REQUIREMENTS,
KeyBlobUsageRequirements::STANDALONE)
.Authorization(TAG_NO_AUTH_REQUIRED)
.Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, ratelimit);
if (!dev.generateKey(paramBuilder, &key)) {
return -1;
}
if (key_out_size) {
*key_out_size = key.size();
}
if (key_buffer_size < key.size()) {
return -1;
}
std::copy(key.data(), key.data() + key.size(), key_buffer);
return 0;
}
int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob,
size_t key_blob_size,
uint32_t ratelimit,
const uint8_t* object,
const size_t object_size,
uint8_t** signature_buffer,
size_t* signature_buffer_size)
{
Keymaster dev;
if (!dev) {
LOG(ERROR) << "Failed to initiate keymaster session";
return -1;
}
if (!key_blob || !object || !signature_buffer || !signature_buffer_size) {
LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument";
return -1;
}
AuthorizationSet outParams;
std::string key(reinterpret_cast<const char*>(key_blob), key_blob_size);
std::string input(reinterpret_cast<const char*>(object), object_size);
std::string output;
KeymasterOperation op;
auto paramBuilder = AuthorizationSetBuilder()
.Authorization(TAG_PADDING, PaddingMode::NONE)
.Authorization(TAG_DIGEST, Digest::NONE);
while (true) {
op = dev.begin(KeyPurpose::SIGN, key, paramBuilder, &outParams);
if (op.errorCode() == ErrorCode::KEY_RATE_LIMIT_EXCEEDED) {
sleep(ratelimit);
continue;
} else break;
}
if (op.errorCode() != ErrorCode::OK) {
LOG(ERROR) << "Error starting keymaster signature transaction: " << int32_t(op.errorCode());
return -1;
}
if (!op.updateCompletely(input, &output)) {
LOG(ERROR) << "Error sending data to keymaster signature transaction: "
<< uint32_t(op.errorCode());
return -1;
}
if (!op.finish(&output)) {
LOG(ERROR) << "Error finalizing keymaster signature transaction: " << int32_t(op.errorCode());
return -1;
}
*signature_buffer = reinterpret_cast<uint8_t*>(malloc(output.size()));
if (*signature_buffer == nullptr) {
LOG(ERROR) << "Error allocation buffer for keymaster signature";
return -1;
}
*signature_buffer_size = output.size();
std::copy(output.data(), output.data() + output.size(), *signature_buffer);
return 0;
}*/
/*
* Copyright (C) 2016 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.
*/
#ifndef ANDROID_VOLD_KEYMASTER_H
#define ANDROID_VOLD_KEYMASTER_H
#ifdef __cplusplus
#include <memory>
#include <string>
#include <utility>
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include <keystore/authorization_set.h>
#include "Utils.h"