From 2478885f3ca47fe2c4073df1100f7bd6ad4931af Mon Sep 17 00:00:00 2001 From: xunchang Date: Fri, 22 Mar 2019 16:08:52 -0700 Subject: Move install to separate module Build libinstall as a shared library. Also drop the dependency on the global variables in common.h. Test: unit tests pass, sideload an OTA Change-Id: I30a20047768ce00689fc0e7851c1c5d712a365a0 --- install/include/install/adb_install.h | 21 ++++++ install/include/install/fuse_sdcard_install.h | 22 ++++++ install/include/install/install.h | 69 ++++++++++++++++++ install/include/install/package.h | 53 ++++++++++++++ install/include/install/verifier.h | 101 ++++++++++++++++++++++++++ install/include/private/asn1_decoder.h | 56 ++++++++++++++ install/include/private/setup_commands.h | 39 ++++++++++ 7 files changed, 361 insertions(+) create mode 100644 install/include/install/adb_install.h create mode 100644 install/include/install/fuse_sdcard_install.h create mode 100644 install/include/install/install.h create mode 100644 install/include/install/package.h create mode 100644 install/include/install/verifier.h create mode 100644 install/include/private/asn1_decoder.h create mode 100644 install/include/private/setup_commands.h (limited to 'install/include') diff --git a/install/include/install/adb_install.h b/install/include/install/adb_install.h new file mode 100644 index 000000000..dbc824501 --- /dev/null +++ b/install/include/install/adb_install.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2012 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. + */ + +#pragma once + +#include + +int apply_from_adb(bool* wipe_cache, RecoveryUI* ui); diff --git a/install/include/install/fuse_sdcard_install.h b/install/include/install/fuse_sdcard_install.h new file mode 100644 index 000000000..345aea45b --- /dev/null +++ b/install/include/install/fuse_sdcard_install.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include "recovery_ui/device.h" +#include "recovery_ui/ui.h" + +int ApplyFromSdcard(Device* device, bool* wipe_cache, RecoveryUI* ui); diff --git a/install/include/install/install.h b/install/include/install/install.h new file mode 100644 index 000000000..74fb3d170 --- /dev/null +++ b/install/include/install/install.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2007 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. + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +#include "package.h" +#include "recovery_ui/ui.h" + +enum InstallResult { + INSTALL_SUCCESS, + INSTALL_ERROR, + INSTALL_CORRUPT, + INSTALL_NONE, + INSTALL_SKIPPED, + INSTALL_RETRY, + INSTALL_KEY_INTERRUPTED +}; + +enum class OtaType { + AB, + BLOCK, + BRICK, +}; + +// Installs the given update package. If INSTALL_SUCCESS is returned and *wipe_cache is true on +// exit, caller should wipe the cache partition. +int install_package(const std::string& package, bool* wipe_cache, bool needs_mount, int retry_count, + RecoveryUI* ui); + +// Verifies the package by ota keys. Returns true if the package is verified successfully, +// otherwise returns false. +bool verify_package(Package* package, RecoveryUI* ui); + +// Reads meta data file of the package; parses each line in the format "key=value"; and writes the +// result to |metadata|. Return true if succeed, otherwise return false. +bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map* metadata); + +// Reads the "recovery.wipe" entry in the zip archive returns a list of partitions to wipe. +std::vector GetWipePartitionList(Package* wipe_package); + +// Verifies the compatibility info in a Treble-compatible package. Returns true directly if the +// entry doesn't exist. +bool verify_package_compatibility(ZipArchiveHandle package_zip); + +// Checks if the the metadata in the OTA package has expected values. Returns 0 on success. +// Mandatory checks: ota-type, pre-device and serial number(if presents) +// AB OTA specific checks: pre-build version, fingerprint, timestamp. +int CheckPackageMetadata(const std::map& metadata, OtaType ota_type); diff --git a/install/include/install/package.h b/install/include/install/package.h new file mode 100644 index 000000000..cd44d10be --- /dev/null +++ b/install/include/install/package.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include + +#include "verifier.h" + +// This class serves as a wrapper for an OTA update package. It aims to provide the common +// interface for both packages loaded in memory and packages read from fd. +class Package : public VerifierInterface { + public: + static std::unique_ptr CreateMemoryPackage( + const std::string& path, const std::function& set_progress); + static std::unique_ptr CreateMemoryPackage( + std::vector content, const std::function& set_progress); + static std::unique_ptr CreateFilePackage(const std::string& path, + const std::function& set_progress); + + virtual ~Package() = default; + + // Opens the package as a zip file and returns the ZipArchiveHandle. + virtual ZipArchiveHandle GetZipArchiveHandle() = 0; + + // Updates the progress in fraction during package verification. + void SetProgress(float progress) override; + + protected: + // An optional function to update the progress. + std::function set_progress_; +}; diff --git a/install/include/install/verifier.h b/install/include/install/verifier.h new file mode 100644 index 000000000..f9e947580 --- /dev/null +++ b/install/include/install/verifier.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2008 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. + */ + +#pragma once + +#include + +#include +#include +#include + +#include +#include +#include + +constexpr size_t MiB = 1024 * 1024; + +using HasherUpdateCallback = std::function; + +struct RSADeleter { + void operator()(RSA* rsa) const { + RSA_free(rsa); + } +}; + +struct ECKEYDeleter { + void operator()(EC_KEY* ec_key) const { + EC_KEY_free(ec_key); + } +}; + +struct Certificate { + typedef enum { + KEY_TYPE_RSA, + KEY_TYPE_EC, + } KeyType; + + Certificate(int hash_len_, KeyType key_type_, std::unique_ptr&& rsa_, + std::unique_ptr&& ec_) + : hash_len(hash_len_), key_type(key_type_), rsa(std::move(rsa_)), ec(std::move(ec_)) {} + + // SHA_DIGEST_LENGTH (SHA-1) or SHA256_DIGEST_LENGTH (SHA-256) + int hash_len; + KeyType key_type; + std::unique_ptr rsa; + std::unique_ptr ec; +}; + +class VerifierInterface { + public: + virtual ~VerifierInterface() = default; + + // Returns the package size in bytes. + virtual uint64_t GetPackageSize() const = 0; + + // Reads |byte_count| data starting from |offset|, and puts the result in |buffer|. + virtual bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) = 0; + + // Updates the hash contexts for |length| bytes data starting from |start|. + virtual bool UpdateHashAtOffset(const std::vector& hashers, uint64_t start, + uint64_t length) = 0; + + // Updates the progress in fraction during package verification. + virtual void SetProgress(float progress) = 0; +}; + +// Looks for an RSA signature embedded in the .ZIP file comment given the path to the zip. +// Verifies that it matches one of the given public keys. Returns VERIFY_SUCCESS or +// VERIFY_FAILURE (if any error is encountered or no key matches the signature). +int verify_file(VerifierInterface* package, const std::vector& keys); + +// Checks that the RSA key has a modulus of 2048 or 4096 bits long, and public exponent is 3 or +// 65537. +bool CheckRSAKey(const std::unique_ptr& rsa); + +// Checks that the field size of the curve for the EC key is 256 bits. +bool CheckECKey(const std::unique_ptr& ec_key); + +// Parses a PEM-encoded x509 certificate from the given buffer and saves it into |cert|. Returns +// false if there is a parsing failure or the signature's encryption algorithm is not supported. +bool LoadCertificateFromBuffer(const std::vector& pem_content, Certificate* cert); + +// Iterates over the zip entries with the suffix "x509.pem" and returns a list of recognized +// certificates. Returns an empty list if we fail to parse any of the entries. +std::vector LoadKeysFromZipfile(const std::string& zip_name); + +#define VERIFY_SUCCESS 0 +#define VERIFY_FAILURE 1 diff --git a/install/include/private/asn1_decoder.h b/install/include/private/asn1_decoder.h new file mode 100644 index 000000000..e5337d9c4 --- /dev/null +++ b/install/include/private/asn1_decoder.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 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 ASN1_DECODER_H_ +#define ASN1_DECODER_H_ + +#include +#include + +class asn1_context { + public: + asn1_context(const uint8_t* buffer, size_t length) : p_(buffer), length_(length), app_type_(0) {} + int asn1_constructed_type() const; + asn1_context* asn1_constructed_get(); + bool asn1_constructed_skip_all(); + asn1_context* asn1_sequence_get(); + asn1_context* asn1_set_get(); + bool asn1_sequence_next(); + bool asn1_oid_get(const uint8_t** oid, size_t* length); + bool asn1_octet_string_get(const uint8_t** octet_string, size_t* length); + + private: + static constexpr int kMaskConstructed = 0xE0; + static constexpr int kMaskTag = 0x7F; + static constexpr int kMaskAppType = 0x1F; + + static constexpr int kTagOctetString = 0x04; + static constexpr int kTagOid = 0x06; + static constexpr int kTagSequence = 0x30; + static constexpr int kTagSet = 0x31; + static constexpr int kTagConstructed = 0xA0; + + int peek_byte() const; + int get_byte(); + bool skip_bytes(size_t num_skip); + bool decode_length(size_t* out_len); + + const uint8_t* p_; + size_t length_; + int app_type_; +}; + +#endif /* ASN1_DECODER_H_ */ diff --git a/install/include/private/setup_commands.h b/install/include/private/setup_commands.h new file mode 100644 index 000000000..7fdc741d6 --- /dev/null +++ b/install/include/private/setup_commands.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 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. + */ + +// Private headers exposed for testing purpose only. + +#pragma once + +#include +#include + +#include + +// Sets up the commands for a non-A/B update. Extracts the updater binary from the open zip archive +// |zip| located at |package|. Stores the command line that should be called into |cmd|. The +// |status_fd| is the file descriptor the child process should use to report back the progress of +// the update. +int SetUpNonAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int retry_count, + int status_fd, std::vector* cmd); + +// Sets up the commands for an A/B update. Extracts the needed entries from the open zip archive +// |zip| located at |package|. Stores the command line that should be called into |cmd|. The +// |status_fd| is the file descriptor the child process should use to report back the progress of +// the update. Note that since this applies to the sideloading flow only, it takes one less +// parameter |retry_count| than the non-A/B version. +int SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd, + std::vector* cmd); -- cgit v1.2.3