diff options
author | Yo Chiang <yochiang@google.com> | 2020-02-05 21:55:40 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-02-05 21:55:40 +0000 |
commit | 0679b298a71fff843b3a2afe673ff11eee871eb6 (patch) | |
tree | 6ed8cc44fa21c4071b399e8ea5d706d65a2057da /gsi_service.cpp | |
parent | 4a3bcc6b7a3f8453c295a32a230e6b18ca954f26 (diff) | |
parent | 53bed1c153304aa7af235dd69877231a5882e0ed (diff) | |
download | gsid-0679b298a71fff843b3a2afe673ff11eee871eb6.tar.gz |
Merge "Add getAvbPublicKey to IGsiService and IImageService"
Diffstat (limited to 'gsi_service.cpp')
-rw-r--r-- | gsi_service.cpp | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/gsi_service.cpp b/gsi_service.cpp index 611f855..83d6957 100644 --- a/gsi_service.cpp +++ b/gsi_service.cpp @@ -25,6 +25,7 @@ #include <sys/vfs.h> #include <unistd.h> +#include <array> #include <chrono> #include <string> #include <vector> @@ -38,8 +39,10 @@ #include <android/gsi/IGsiService.h> #include <ext4_utils/ext4_utils.h> #include <fs_mgr.h> +#include <libavb/libavb.h> #include <libdm/dm.h> #include <libfiemap/image_manager.h> +#include <openssl/sha.h> #include <private/android_filesystem_config.h> #include "file_paths.h" @@ -52,6 +55,7 @@ using namespace std::literals; using namespace android::fs_mgr; using namespace android::fiemap; using android::base::ReadFileToString; +using android::base::ReadFullyAtOffset; using android::base::RemoveFileIfExists; using android::base::StringPrintf; using android::base::unique_fd; @@ -66,6 +70,8 @@ android::wp<GsiService> GsiService::sInstance; // Default userdata image size. static constexpr int64_t kDefaultUserdataSize = int64_t(2) * 1024 * 1024 * 1024; +static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst); + void Gsid::Register() { auto ret = android::BinderService<Gsid>::publish(); if (ret != android::OK) { @@ -440,6 +446,24 @@ binder::Status GsiService::dumpDeviceMapperDevices(std::string* _aidl_return) { return binder::Status::ok(); } +binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_return) { + ENFORCE_SYSTEM; + std::lock_guard<std::mutex> guard(parent_->lock()); + + if (!installer_) { + *_aidl_return = INSTALL_ERROR_GENERIC; + return binder::Status::ok(); + } + int fd = installer_->GetPartitionFd(); + if (!GetAvbPublicKeyFromFd(fd, dst)) { + LOG(ERROR) << "Failed to extract AVB public key"; + *_aidl_return = INSTALL_ERROR_GENERIC; + return binder::Status::ok(); + } + *_aidl_return = INSTALL_OK; + return binder::Status::ok(); +} + bool GsiService::CreateInstallStatusFile() { if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) { PLOG(ERROR) << "write " << kDsuInstallStatusFile; @@ -482,6 +506,8 @@ class ImageService : public BinderService<ImageService>, public BnImageService { binder::Status unmapImageDevice(const std::string& name) override; binder::Status backingImageExists(const std::string& name, bool* _aidl_return) override; binder::Status isImageMapped(const std::string& name, bool* _aidl_return) override; + binder::Status getAvbPublicKey(const std::string& name, AvbPublicKey* dst, + int32_t* _aidl_return) override; binder::Status zeroFillNewImage(const std::string& name, int64_t bytes) override; binder::Status removeAllImages() override; binder::Status removeDisabledImages() override; @@ -582,6 +608,46 @@ binder::Status ImageService::isImageMapped(const std::string& name, bool* _aidl_ return binder::Status::ok(); } +binder::Status ImageService::getAvbPublicKey(const std::string& name, AvbPublicKey* dst, + int32_t* _aidl_return) { + if (!CheckUid()) return UidSecurityError(); + + std::lock_guard<std::mutex> guard(parent_->lock()); + + std::string device_path; + std::unique_ptr<MappedDevice> mapped_device; + if (!impl_->IsImageMapped(name)) { + mapped_device = MappedDevice::Open(impl_.get(), 10s, name); + if (!mapped_device) { + PLOG(ERROR) << "Fail to map image: " << name; + *_aidl_return = IMAGE_ERROR; + return binder::Status::ok(); + } + device_path = mapped_device->path(); + } else { + if (!impl_->GetMappedImageDevice(name, &device_path)) { + PLOG(ERROR) << "GetMappedImageDevice() failed"; + *_aidl_return = IMAGE_ERROR; + return binder::Status::ok(); + } + } + android::base::unique_fd fd(open(device_path.c_str(), O_RDONLY | O_CLOEXEC)); + if (!fd.ok()) { + PLOG(ERROR) << "Fail to open mapped device: " << device_path; + *_aidl_return = IMAGE_ERROR; + return binder::Status::ok(); + } + bool ok = GetAvbPublicKeyFromFd(fd.get(), dst); + fd = {}; + if (!ok) { + LOG(ERROR) << "Failed to extract AVB public key"; + *_aidl_return = IMAGE_ERROR; + return binder::Status::ok(); + } + *_aidl_return = IMAGE_OK; + return binder::Status::ok(); +} + binder::Status ImageService::zeroFillNewImage(const std::string& name, int64_t bytes) { if (!CheckUid()) return UidSecurityError(); @@ -934,5 +1000,47 @@ void GsiService::RunStartupTasks() { } } +static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) { + // Read the AVB footer from EOF. + int64_t total_size = get_block_device_size(fd); + int64_t footer_offset = total_size - AVB_FOOTER_SIZE; + std::array<uint8_t, AVB_FOOTER_SIZE> footer_bytes; + if (!ReadFullyAtOffset(fd, footer_bytes.data(), AVB_FOOTER_SIZE, footer_offset)) { + PLOG(ERROR) << "cannot read AVB footer"; + return false; + } + // Validate the AVB footer data and byte swap to native byte order. + AvbFooter footer; + if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_bytes.data(), &footer)) { + LOG(ERROR) << "invalid AVB footer"; + return false; + } + // Read the VBMeta image. + std::vector<uint8_t> vbmeta_bytes(footer.vbmeta_size); + if (!ReadFullyAtOffset(fd, vbmeta_bytes.data(), vbmeta_bytes.size(), footer.vbmeta_offset)) { + PLOG(ERROR) << "cannot read VBMeta image"; + return false; + } + // Validate the VBMeta image and retrieve AVB public key. + // After a successful call to avb_vbmeta_image_verify(), public_key_data + // will point to the serialized AVB public key, in the same format generated + // by the `avbtool extract_public_key` command. + const uint8_t* public_key_data; + size_t public_key_size; + AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(vbmeta_bytes.data(), vbmeta_bytes.size(), + &public_key_data, &public_key_size); + if (result != AVB_VBMETA_VERIFY_RESULT_OK) { + LOG(ERROR) << "invalid VBMeta image: " << avb_vbmeta_verify_result_to_string(result); + return false; + } + if (public_key_data != nullptr) { + dst->bytes.resize(public_key_size); + memcpy(dst->bytes.data(), public_key_data, public_key_size); + dst->sha1.resize(SHA_DIGEST_LENGTH); + SHA1(public_key_data, public_key_size, dst->sha1.data()); + } + return true; +} + } // namespace gsi } // namespace android |