[apkverify] Refactor verify_signed_data to use SignatureAlgorithmID
This CL refactor verify_signed_data to use SignatureAlgorithmID
enum instead of the raw integers. There's no behavior change in
this CL.
Bug: 246254355
Test: libapkverify.integration_test
Change-Id: I1296efb9a700d2fe3f6ec93f69cdc407a6882a0d
diff --git a/libs/apkverify/src/algorithms.rs b/libs/apkverify/src/algorithms.rs
index f15f0a4..ee9c869 100644
--- a/libs/apkverify/src/algorithms.rs
+++ b/libs/apkverify/src/algorithms.rs
@@ -16,9 +16,12 @@
//! Algorithms used for APK Signature Scheme.
-use anyhow::{bail, Result};
+use anyhow::{bail, ensure, Result};
use num_derive::FromPrimitive;
use openssl::hash::MessageDigest;
+use openssl::pkey::{self, PKey};
+use openssl::rsa::Padding;
+use openssl::sign::Verifier;
use std::cmp::Ordering;
/// [Signature Algorithm IDs]: https://source.android.com/docs/security/apksigning/v2#signature-algorithm-ids
@@ -76,6 +79,77 @@
}
}
}
+
+ pub(crate) fn new_verifier<'a>(
+ &self,
+ public_key: &'a PKey<pkey::Public>,
+ ) -> Result<Verifier<'a>> {
+ ensure!(
+ !matches!(
+ self,
+ SignatureAlgorithmID::EcdsaWithSha512
+ | SignatureAlgorithmID::DsaWithSha256
+ | SignatureAlgorithmID::VerityDsaWithSha256
+ ),
+ "TODO(b/197052981): Algorithm '{:#?}' is not implemented.",
+ self
+ );
+ ensure!(public_key.id() == self.pkey_id(), "Public key has the wrong ID");
+ let mut verifier = Verifier::new(self.new_message_digest(), public_key)?;
+ if public_key.id() == pkey::Id::RSA {
+ verifier.set_rsa_padding(self.rsa_padding())?;
+ }
+ Ok(verifier)
+ }
+
+ /// Returns the message digest corresponding to the signature algorithm
+ /// according to the spec [Signature Algorithm IDs].
+ fn new_message_digest(&self) -> MessageDigest {
+ match self {
+ SignatureAlgorithmID::RsaPssWithSha256
+ | SignatureAlgorithmID::RsaPkcs1V15WithSha256
+ | SignatureAlgorithmID::EcdsaWithSha256
+ | SignatureAlgorithmID::DsaWithSha256
+ | SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256
+ | SignatureAlgorithmID::VerityEcdsaWithSha256
+ | SignatureAlgorithmID::VerityDsaWithSha256 => MessageDigest::sha256(),
+ SignatureAlgorithmID::RsaPssWithSha512
+ | SignatureAlgorithmID::RsaPkcs1V15WithSha512
+ | SignatureAlgorithmID::EcdsaWithSha512 => MessageDigest::sha512(),
+ }
+ }
+
+ fn pkey_id(&self) -> pkey::Id {
+ match self {
+ SignatureAlgorithmID::RsaPssWithSha256
+ | SignatureAlgorithmID::RsaPssWithSha512
+ | SignatureAlgorithmID::RsaPkcs1V15WithSha256
+ | SignatureAlgorithmID::RsaPkcs1V15WithSha512
+ | SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256 => pkey::Id::RSA,
+ SignatureAlgorithmID::EcdsaWithSha256
+ | SignatureAlgorithmID::EcdsaWithSha512
+ | SignatureAlgorithmID::VerityEcdsaWithSha256 => pkey::Id::EC,
+ SignatureAlgorithmID::DsaWithSha256 | SignatureAlgorithmID::VerityDsaWithSha256 => {
+ pkey::Id::DSA
+ }
+ }
+ }
+
+ fn rsa_padding(&self) -> Padding {
+ match self {
+ SignatureAlgorithmID::RsaPssWithSha256 | SignatureAlgorithmID::RsaPssWithSha512 => {
+ Padding::PKCS1_PSS
+ }
+ SignatureAlgorithmID::RsaPkcs1V15WithSha256
+ | SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256
+ | SignatureAlgorithmID::RsaPkcs1V15WithSha512 => Padding::PKCS1,
+ SignatureAlgorithmID::EcdsaWithSha256
+ | SignatureAlgorithmID::EcdsaWithSha512
+ | SignatureAlgorithmID::VerityEcdsaWithSha256
+ | SignatureAlgorithmID::DsaWithSha256
+ | SignatureAlgorithmID::VerityDsaWithSha256 => Padding::NONE,
+ }
+ }
}
/// The rank of the content digest algorithm in this enum is used to help pick
diff --git a/libs/apkverify/src/sigutil.rs b/libs/apkverify/src/sigutil.rs
index ea6d63a..98edf49 100644
--- a/libs/apkverify/src/sigutil.rs
+++ b/libs/apkverify/src/sigutil.rs
@@ -16,6 +16,10 @@
//! Utilities for Signature Verification
+// TODO(b/246254355): Remove this once we migrate all the usages of
+// raw signature algorithm id to the enum.
+#![allow(dead_code)]
+
use anyhow::{anyhow, ensure, Error, Result};
use byteorder::{LittleEndian, ReadBytesExt};
use bytes::{Buf, BufMut, Bytes, BytesMut};
diff --git a/libs/apkverify/src/v3.rs b/libs/apkverify/src/v3.rs
index c86696f..2f13837 100644
--- a/libs/apkverify/src/v3.rs
+++ b/libs/apkverify/src/v3.rs
@@ -21,10 +21,7 @@
use anyhow::{anyhow, bail, ensure, Context, Result};
use bytes::Bytes;
use num_traits::FromPrimitive;
-use openssl::hash::MessageDigest;
use openssl::pkey::{self, PKey};
-use openssl::rsa::Padding;
-use openssl::sign::Verifier;
use openssl::x509::X509;
use std::fs::File;
use std::io::{Read, Seek};
@@ -223,39 +220,14 @@
}
}
-fn verify_signed_data(data: &Bytes, signature: &Signature, key: &PKey<pkey::Public>) -> Result<()> {
- let (pkey_id, padding, digest) = match signature.signature_algorithm_id {
- SIGNATURE_RSA_PSS_WITH_SHA256 => {
- (pkey::Id::RSA, Padding::PKCS1_PSS, MessageDigest::sha256())
- }
- SIGNATURE_RSA_PSS_WITH_SHA512 => {
- (pkey::Id::RSA, Padding::PKCS1_PSS, MessageDigest::sha512())
- }
- SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256 | SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 => {
- (pkey::Id::RSA, Padding::PKCS1, MessageDigest::sha256())
- }
- SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512 => {
- (pkey::Id::RSA, Padding::PKCS1, MessageDigest::sha512())
- }
- SIGNATURE_ECDSA_WITH_SHA256 | SIGNATURE_VERITY_ECDSA_WITH_SHA256 => {
- (pkey::Id::EC, Padding::NONE, MessageDigest::sha256())
- }
- // TODO(b/190343842) not implemented signature algorithm
- SIGNATURE_ECDSA_WITH_SHA512
- | SIGNATURE_DSA_WITH_SHA256
- | SIGNATURE_VERITY_DSA_WITH_SHA256 => {
- bail!(
- "TODO(b/190343842) not implemented signature algorithm: {:#x}",
- signature.signature_algorithm_id
- );
- }
- _ => bail!("Unsupported signature algorithm: {:#x}", signature.signature_algorithm_id),
- };
- ensure!(key.id() == pkey_id, "Public key has the wrong ID");
- let mut verifier = Verifier::new(digest, key)?;
- if pkey_id == pkey::Id::RSA {
- verifier.set_rsa_padding(padding)?;
- }
+fn verify_signed_data(
+ data: &Bytes,
+ signature: &Signature,
+ public_key: &PKey<pkey::Public>,
+) -> Result<()> {
+ let mut verifier = SignatureAlgorithmID::from_u32(signature.signature_algorithm_id)
+ .context("Unsupported algorithm")?
+ .new_verifier(public_key)?;
verifier.update(data)?;
let verified = verifier.verify(&signature.signature)?;
ensure!(verified, "Signature is invalid ");
diff --git a/libs/apkverify/tests/apkverify_test.rs b/libs/apkverify/tests/apkverify_test.rs
index a674ad7..0b33208 100644
--- a/libs/apkverify/tests/apkverify_test.rs
+++ b/libs/apkverify/tests/apkverify_test.rs
@@ -43,10 +43,7 @@
for key_name in KEY_NAMES_DSA.iter() {
let res = verify(format!("tests/data/v3-only-with-dsa-sha256-{}.apk", key_name));
assert!(res.is_err());
- assert_contains(
- &res.unwrap_err().to_string(),
- "TODO(b/190343842) not implemented signature algorithm",
- );
+ assert_contains(&res.unwrap_err().to_string(), "not implemented");
}
}
@@ -63,10 +60,7 @@
for key_name in KEY_NAMES_ECDSA.iter() {
let res = verify(format!("tests/data/v3-only-with-ecdsa-sha512-{}.apk", key_name));
assert!(res.is_err());
- assert_contains(
- &res.unwrap_err().to_string(),
- "TODO(b/190343842) not implemented signature algorithm",
- );
+ assert_contains(&res.unwrap_err().to_string(), "not implemented");
}
}
@@ -101,8 +95,7 @@
assert!(res.is_err());
let error_msg = &res.unwrap_err().to_string();
assert!(
- error_msg.contains("Signature is invalid")
- || error_msg.contains("TODO(b/190343842) not implemented signature algorithm")
+ error_msg.contains("Signature is invalid") || error_msg.contains("not implemented")
);
}
}
@@ -118,10 +111,7 @@
let res = verify(path);
assert!(res.is_err());
let error_msg = &res.unwrap_err().to_string();
- assert!(
- error_msg.contains("Digest mismatch")
- || error_msg.contains("TODO(b/190343842) not implemented signature algorithm")
- );
+ assert!(error_msg.contains("Digest mismatch") || error_msg.contains("not implemented"));
}
}