Loading tests/component/verifier_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ #include <android-base/test_utils.h> #include <android-base/unique_fd.h> #include <gtest/gtest.h> #include <openssl/bn.h> #include <openssl/ec.h> #include <openssl/nid.h> #include <ziparchive/zip_writer.h> #include "common/test_constants.h" Loading Loading @@ -148,6 +151,35 @@ TEST(VerifierTest, LoadCertificateFromBuffer_sha256_ec256bits) { VerifyPackageWithSingleCertificate("otasigned_v5.zip", std::move(cert)); } TEST(VerifierTest, LoadCertificateFromBuffer_check_rsa_keys) { std::unique_ptr<RSA, RSADeleter> rsa(RSA_new()); std::unique_ptr<BIGNUM, decltype(&BN_free)> exponent(BN_new(), BN_free); BN_set_word(exponent.get(), 3); RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr); ASSERT_TRUE(CheckRSAKey(rsa)); // Exponent is expected to be 3 or 65537 BN_set_word(exponent.get(), 17); RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr); ASSERT_FALSE(CheckRSAKey(rsa)); // Modulus is expected to be 2048. BN_set_word(exponent.get(), 3); RSA_generate_key_ex(rsa.get(), 1024, exponent.get(), nullptr); ASSERT_FALSE(CheckRSAKey(rsa)); } TEST(VerifierTest, LoadCertificateFromBuffer_check_ec_keys) { std::unique_ptr<EC_KEY, ECKEYDeleter> ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); ASSERT_EQ(1, EC_KEY_generate_key(ec.get())); ASSERT_TRUE(CheckECKey(ec)); // Expects 256-bit EC key with curve NIST P-256 ec.reset(EC_KEY_new_by_curve_name(NID_secp224r1)); ASSERT_EQ(1, EC_KEY_generate_key(ec.get())); ASSERT_FALSE(CheckECKey(ec)); } TEST(VerifierTest, LoadKeysFromZipfile_empty_archive) { TemporaryFile otacerts; BuildCertificateArchive({}, otacerts.release()); Loading verifier.cpp +46 −6 Original line number Diff line number Diff line Loading @@ -500,6 +500,48 @@ std::vector<Certificate> LoadKeysFromZipfile(const std::string& zip_name) { return result; } bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa) { if (!rsa) { return false; } const BIGNUM* out_n; const BIGNUM* out_e; RSA_get0_key(rsa.get(), &out_n, &out_e, nullptr /* private exponent */); auto modulus_bits = BN_num_bits(out_n); if (modulus_bits != 2048) { LOG(ERROR) << "Modulus should be 2048 bits long, actual: " << modulus_bits; return false; } BN_ULONG exponent = BN_get_word(out_e); if (exponent != 3 && exponent != 65537) { LOG(ERROR) << "Public exponent should be 3 or 65537, actual: " << exponent; return false; } return true; } bool CheckECKey(const std::unique_ptr<EC_KEY, ECKEYDeleter>& ec_key) { if (!ec_key) { return false; } const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get()); if (!ec_group) { LOG(ERROR) << "Failed to get the ec_group from the ec_key"; return false; } auto degree = EC_GROUP_get_degree(ec_group); if (degree != 256) { LOG(ERROR) << "Field size of the ec key should be 256 bits long, actual: " << degree; return false; } return true; } bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certificate* cert) { std::unique_ptr<BIO, decltype(&BIO_free)> content( BIO_new_mem_buf(pem_content.data(), pem_content.size()), BIO_free); Loading Loading @@ -538,22 +580,20 @@ bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certific } int key_type = EVP_PKEY_id(public_key.get()); // TODO(xunchang) check the rsa key has exponent 3 or 65537 with RSA_get0_key; and ec key is // 256 bits. if (key_type == EVP_PKEY_RSA) { cert->key_type = Certificate::KEY_TYPE_RSA; cert->ec.reset(); cert->rsa.reset(EVP_PKEY_get1_RSA(public_key.get())); if (!cert->rsa) { LOG(ERROR) << "Failed to get the rsa key info from public key"; if (!cert->rsa || !CheckRSAKey(cert->rsa)) { LOG(ERROR) << "Failed to validate the rsa key info from public key"; return false; } } else if (key_type == EVP_PKEY_EC) { cert->key_type = Certificate::KEY_TYPE_EC; cert->rsa.reset(); cert->ec.reset(EVP_PKEY_get1_EC_KEY(public_key.get())); if (!cert->ec) { LOG(ERROR) << "Failed to get the ec key info from the public key"; if (!cert->ec || !CheckECKey(cert->ec)) { LOG(ERROR) << "Failed to validate the ec key info from the public key"; return false; } } else { Loading verifier.h +6 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,12 @@ int verify_file(const unsigned char* addr, size_t length, const std::vector<Cert bool load_keys(const char* filename, std::vector<Certificate>& certs); // Checks that the RSA key has a modulus of 2048 bits long, and public exponent is 3 or 65537. bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa); // Checks that the field size of the curve for the EC key is 256 bits. bool CheckECKey(const std::unique_ptr<EC_KEY, ECKEYDeleter>& 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<uint8_t>& pem_content, Certificate* cert); Loading Loading
tests/component/verifier_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ #include <android-base/test_utils.h> #include <android-base/unique_fd.h> #include <gtest/gtest.h> #include <openssl/bn.h> #include <openssl/ec.h> #include <openssl/nid.h> #include <ziparchive/zip_writer.h> #include "common/test_constants.h" Loading Loading @@ -148,6 +151,35 @@ TEST(VerifierTest, LoadCertificateFromBuffer_sha256_ec256bits) { VerifyPackageWithSingleCertificate("otasigned_v5.zip", std::move(cert)); } TEST(VerifierTest, LoadCertificateFromBuffer_check_rsa_keys) { std::unique_ptr<RSA, RSADeleter> rsa(RSA_new()); std::unique_ptr<BIGNUM, decltype(&BN_free)> exponent(BN_new(), BN_free); BN_set_word(exponent.get(), 3); RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr); ASSERT_TRUE(CheckRSAKey(rsa)); // Exponent is expected to be 3 or 65537 BN_set_word(exponent.get(), 17); RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr); ASSERT_FALSE(CheckRSAKey(rsa)); // Modulus is expected to be 2048. BN_set_word(exponent.get(), 3); RSA_generate_key_ex(rsa.get(), 1024, exponent.get(), nullptr); ASSERT_FALSE(CheckRSAKey(rsa)); } TEST(VerifierTest, LoadCertificateFromBuffer_check_ec_keys) { std::unique_ptr<EC_KEY, ECKEYDeleter> ec(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); ASSERT_EQ(1, EC_KEY_generate_key(ec.get())); ASSERT_TRUE(CheckECKey(ec)); // Expects 256-bit EC key with curve NIST P-256 ec.reset(EC_KEY_new_by_curve_name(NID_secp224r1)); ASSERT_EQ(1, EC_KEY_generate_key(ec.get())); ASSERT_FALSE(CheckECKey(ec)); } TEST(VerifierTest, LoadKeysFromZipfile_empty_archive) { TemporaryFile otacerts; BuildCertificateArchive({}, otacerts.release()); Loading
verifier.cpp +46 −6 Original line number Diff line number Diff line Loading @@ -500,6 +500,48 @@ std::vector<Certificate> LoadKeysFromZipfile(const std::string& zip_name) { return result; } bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa) { if (!rsa) { return false; } const BIGNUM* out_n; const BIGNUM* out_e; RSA_get0_key(rsa.get(), &out_n, &out_e, nullptr /* private exponent */); auto modulus_bits = BN_num_bits(out_n); if (modulus_bits != 2048) { LOG(ERROR) << "Modulus should be 2048 bits long, actual: " << modulus_bits; return false; } BN_ULONG exponent = BN_get_word(out_e); if (exponent != 3 && exponent != 65537) { LOG(ERROR) << "Public exponent should be 3 or 65537, actual: " << exponent; return false; } return true; } bool CheckECKey(const std::unique_ptr<EC_KEY, ECKEYDeleter>& ec_key) { if (!ec_key) { return false; } const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get()); if (!ec_group) { LOG(ERROR) << "Failed to get the ec_group from the ec_key"; return false; } auto degree = EC_GROUP_get_degree(ec_group); if (degree != 256) { LOG(ERROR) << "Field size of the ec key should be 256 bits long, actual: " << degree; return false; } return true; } bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certificate* cert) { std::unique_ptr<BIO, decltype(&BIO_free)> content( BIO_new_mem_buf(pem_content.data(), pem_content.size()), BIO_free); Loading Loading @@ -538,22 +580,20 @@ bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certific } int key_type = EVP_PKEY_id(public_key.get()); // TODO(xunchang) check the rsa key has exponent 3 or 65537 with RSA_get0_key; and ec key is // 256 bits. if (key_type == EVP_PKEY_RSA) { cert->key_type = Certificate::KEY_TYPE_RSA; cert->ec.reset(); cert->rsa.reset(EVP_PKEY_get1_RSA(public_key.get())); if (!cert->rsa) { LOG(ERROR) << "Failed to get the rsa key info from public key"; if (!cert->rsa || !CheckRSAKey(cert->rsa)) { LOG(ERROR) << "Failed to validate the rsa key info from public key"; return false; } } else if (key_type == EVP_PKEY_EC) { cert->key_type = Certificate::KEY_TYPE_EC; cert->rsa.reset(); cert->ec.reset(EVP_PKEY_get1_EC_KEY(public_key.get())); if (!cert->ec) { LOG(ERROR) << "Failed to get the ec key info from the public key"; if (!cert->ec || !CheckECKey(cert->ec)) { LOG(ERROR) << "Failed to validate the ec key info from the public key"; return false; } } else { Loading
verifier.h +6 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,12 @@ int verify_file(const unsigned char* addr, size_t length, const std::vector<Cert bool load_keys(const char* filename, std::vector<Certificate>& certs); // Checks that the RSA key has a modulus of 2048 bits long, and public exponent is 3 or 65537. bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa); // Checks that the field size of the curve for the EC key is 256 bits. bool CheckECKey(const std::unique_ptr<EC_KEY, ECKEYDeleter>& 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<uint8_t>& pem_content, Certificate* cert); Loading