blob: 03cb4bbbbd10a738235fdf10c29559727bf5b79b [file] [log] [blame]
Jooyung Han12a0b702021-08-05 23:20:31 +09001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Alice Wang3c016622022-09-19 09:08:27 +000017use apkverify::{get_public_key_der, testing::assert_contains, verify};
Alice Wang67d3c002022-09-16 10:08:25 +000018use std::{fs, matches, path::Path};
Jooyung Hand8397852021-08-10 16:29:36 +090019
Seungjae Yoo91e250a2022-06-07 02:21:56 +000020const KEY_NAMES_DSA: &[&str] = &["1024", "2048", "3072"];
21const KEY_NAMES_ECDSA: &[&str] = &["p256", "p384", "p521"];
22const KEY_NAMES_RSA: &[&str] = &["1024", "2048", "3072", "4096", "8192", "16384"];
Jooyung Hancee6de62021-08-11 15:52:07 +090023
24#[test]
25fn test_verify_truncated_cd() {
26 use zip::result::ZipError;
27 let res = verify("tests/data/v2-only-truncated-cd.apk");
Alice Wang92889352022-09-16 10:42:52 +000028 // TODO(b/190343842): consider making a helper for err assertion
Jooyung Hancee6de62021-08-11 15:52:07 +090029 assert!(matches!(
Andrew Walbran117cd5e2021-08-13 11:42:13 +000030 res.unwrap_err().root_cause().downcast_ref::<ZipError>().unwrap(),
Jooyung Hancee6de62021-08-11 15:52:07 +090031 ZipError::InvalidArchive(_),
32 ));
33}
Seungjae Yoo91e250a2022-06-07 02:21:56 +000034
35#[test]
36fn test_verify_v3() {
Alice Wang67d3c002022-09-16 10:08:25 +000037 validate_apk_public_key("tests/data/test.apex");
Seungjae Yoo91e250a2022-06-07 02:21:56 +000038}
39
Seungjae Yoo91e250a2022-06-07 02:21:56 +000040#[test]
41fn test_verify_v3_dsa_sha256() {
42 for key_name in KEY_NAMES_DSA.iter() {
43 let res = verify(format!("tests/data/v3-only-with-dsa-sha256-{}.apk", key_name));
44 assert!(res.is_err());
Alice Wanga66b5c02022-09-16 07:25:17 +000045 assert_contains(&res.unwrap_err().to_string(), "not implemented");
Seungjae Yoo91e250a2022-06-07 02:21:56 +000046 }
47}
48
49#[test]
50fn test_verify_v3_ecdsa_sha256() {
51 for key_name in KEY_NAMES_ECDSA.iter() {
Alice Wang67d3c002022-09-16 10:08:25 +000052 validate_apk_public_key(format!("tests/data/v3-only-with-ecdsa-sha256-{}.apk", key_name));
Seungjae Yoo91e250a2022-06-07 02:21:56 +000053 }
54}
55
Seungjae Yoo91e250a2022-06-07 02:21:56 +000056#[test]
57fn test_verify_v3_ecdsa_sha512() {
58 for key_name in KEY_NAMES_ECDSA.iter() {
Alice Wang67d3c002022-09-16 10:08:25 +000059 validate_apk_public_key(format!("tests/data/v3-only-with-ecdsa-sha512-{}.apk", key_name));
Seungjae Yoo91e250a2022-06-07 02:21:56 +000060 }
61}
62
63#[test]
64fn test_verify_v3_rsa_sha256() {
65 for key_name in KEY_NAMES_RSA.iter() {
Alice Wang67d3c002022-09-16 10:08:25 +000066 validate_apk_public_key(format!(
67 "tests/data/v3-only-with-rsa-pkcs1-sha256-{}.apk",
68 key_name
69 ));
Seungjae Yoo91e250a2022-06-07 02:21:56 +000070 }
71}
72
73#[test]
74fn test_verify_v3_rsa_sha512() {
75 for key_name in KEY_NAMES_RSA.iter() {
Alice Wang67d3c002022-09-16 10:08:25 +000076 validate_apk_public_key(format!(
77 "tests/data/v3-only-with-rsa-pkcs1-sha512-{}.apk",
78 key_name
79 ));
Seungjae Yoo91e250a2022-06-07 02:21:56 +000080 }
81}
82
Seungjae Yoo91e250a2022-06-07 02:21:56 +000083#[test]
84fn test_verify_v3_sig_does_not_verify() {
85 let path_list = [
86 "tests/data/v3-only-with-dsa-sha256-2048-sig-does-not-verify.apk",
87 "tests/data/v3-only-with-ecdsa-sha512-p521-sig-does-not-verify.apk",
88 "tests/data/v3-only-with-rsa-pkcs1-sha256-3072-sig-does-not-verify.apk",
89 ];
90 for path in path_list.iter() {
91 let res = verify(path);
92 assert!(res.is_err());
93 let error_msg = &res.unwrap_err().to_string();
94 assert!(
Alice Wanga66b5c02022-09-16 07:25:17 +000095 error_msg.contains("Signature is invalid") || error_msg.contains("not implemented")
Seungjae Yoo91e250a2022-06-07 02:21:56 +000096 );
97 }
98}
99
Seungjae Yoo91e250a2022-06-07 02:21:56 +0000100#[test]
101fn test_verify_v3_digest_mismatch() {
102 let path_list = [
103 "tests/data/v3-only-with-dsa-sha256-3072-digest-mismatch.apk",
104 "tests/data/v3-only-with-rsa-pkcs1-sha512-8192-digest-mismatch.apk",
105 ];
106 for path in path_list.iter() {
107 let res = verify(path);
108 assert!(res.is_err());
109 let error_msg = &res.unwrap_err().to_string();
Alice Wanga66b5c02022-09-16 07:25:17 +0000110 assert!(error_msg.contains("Digest mismatch") || error_msg.contains("not implemented"));
Seungjae Yoo91e250a2022-06-07 02:21:56 +0000111 }
112}
113
114#[test]
115fn test_verify_v3_wrong_apk_sig_block_magic() {
116 let res = verify("tests/data/v3-only-with-ecdsa-sha512-p384-wrong-apk-sig-block-magic.apk");
117 assert!(res.is_err());
118 assert_contains(&res.unwrap_err().to_string(), "No APK Signing Block");
119}
120
121#[test]
122fn test_verify_v3_apk_sig_block_size_mismatch() {
123 let res =
124 verify("tests/data/v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk");
125 assert!(res.is_err());
126 assert_contains(
127 &res.unwrap_err().to_string(),
128 "APK Signing Block sizes in header and footer do not match",
129 );
130}
131
132#[test]
133fn test_verify_v3_cert_and_public_key_mismatch() {
134 let res = verify("tests/data/v3-only-cert-and-public-key-mismatch.apk");
135 assert!(res.is_err());
136 assert_contains(&res.unwrap_err().to_string(), "Public key mismatch");
137}
138
139#[test]
140fn test_verify_v3_empty() {
141 let res = verify("tests/data/v3-only-empty.apk");
142 assert!(res.is_err());
143 assert_contains(&res.unwrap_err().to_string(), "APK too small for APK Signing Block");
144}
145
146#[test]
147fn test_verify_v3_no_certs_in_sig() {
148 let res = verify("tests/data/v3-only-no-certs-in-sig.apk");
149 assert!(res.is_err());
150 assert_contains(&res.unwrap_err().to_string(), "No certificates listed");
151}
152
153#[test]
154fn test_verify_v3_no_supported_sig_algs() {
155 let res = verify("tests/data/v3-only-no-supported-sig-algs.apk");
156 assert!(res.is_err());
157 assert_contains(&res.unwrap_err().to_string(), "No supported signatures found");
158}
159
160#[test]
161fn test_verify_v3_signatures_and_digests_block_mismatch() {
162 let res = verify("tests/data/v3-only-signatures-and-digests-block-mismatch.apk");
163 assert!(res.is_err());
164 assert_contains(
165 &res.unwrap_err().to_string(),
166 "Signature algorithms don't match between digests and signatures records",
167 );
168}
169
170#[test]
171fn test_verify_v3_unknown_additional_attr() {
Alice Wang67d3c002022-09-16 10:08:25 +0000172 validate_apk_public_key("tests/data/v3-only-unknown-additional-attr.apk");
Seungjae Yoo91e250a2022-06-07 02:21:56 +0000173}
174
175#[test]
176fn test_verify_v3_unknown_pair_in_apk_sig_block() {
Alice Wang67d3c002022-09-16 10:08:25 +0000177 validate_apk_public_key("tests/data/v3-only-unknown-pair-in-apk-sig-block.apk");
Seungjae Yoo91e250a2022-06-07 02:21:56 +0000178}
179
180#[test]
181fn test_verify_v3_ignorable_unsupported_sig_algs() {
Alice Wang67d3c002022-09-16 10:08:25 +0000182 validate_apk_public_key("tests/data/v3-only-with-ignorable-unsupported-sig-algs.apk");
Seungjae Yoo91e250a2022-06-07 02:21:56 +0000183}
184
185#[test]
186fn test_verify_v3_stamp() {
Alice Wang67d3c002022-09-16 10:08:25 +0000187 validate_apk_public_key("tests/data/v3-only-with-stamp.apk");
188}
189
190fn validate_apk_public_key<P: AsRef<Path>>(apk_path: P) {
191 // Validates public key from verification == expected public key.
192 let public_key_from_verification = verify(apk_path.as_ref());
193 let public_key_from_verification =
194 public_key_from_verification.expect("Error in verification result");
195
196 let expected_public_key_path = format!("{}.der", apk_path.as_ref().to_str().unwrap());
197 assert!(
198 fs::metadata(&expected_public_key_path).is_ok(),
199 "File does not exist. You can re-create it with:\n$ echo -en {} > {}\n",
200 public_key_from_verification.iter().map(|b| format!("\\\\x{:02x}", b)).collect::<String>(),
201 expected_public_key_path
202 );
203 let expected_public_key = fs::read(&expected_public_key_path).unwrap();
204 assert_eq!(
205 expected_public_key,
206 public_key_from_verification.as_ref(),
207 "{}",
208 expected_public_key_path
209 );
210
Alice Wang3c016622022-09-19 09:08:27 +0000211 // Validates public key extracted directly from apk
Alice Wang67d3c002022-09-16 10:08:25 +0000212 // (without verification) == expected public key.
Alice Wang3c016622022-09-19 09:08:27 +0000213 let public_key_from_apk = get_public_key_der(apk_path.as_ref());
214 let public_key_from_apk =
215 public_key_from_apk.expect("Error when extracting public key from apk");
216 assert_eq!(expected_public_key, public_key_from_apk.as_ref(), "{}", expected_public_key_path);
Seungjae Yoo91e250a2022-06-07 02:21:56 +0000217}