blob: f15f0a48bff74f4896337aab2009f81efa3f6069 [file] [log] [blame]
Alice Wang5d0f89a2022-09-15 15:06:10 +00001/*
2 * Copyright (C) 2022 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
17//! Algorithms used for APK Signature Scheme.
18
19use anyhow::{bail, Result};
20use num_derive::FromPrimitive;
21use openssl::hash::MessageDigest;
22use std::cmp::Ordering;
23
24/// [Signature Algorithm IDs]: https://source.android.com/docs/security/apksigning/v2#signature-algorithm-ids
25///
26/// Some of the algorithms are not implemented. See b/197052981.
27#[derive(Clone, Debug, Eq, FromPrimitive)]
28#[repr(u32)]
29pub enum SignatureAlgorithmID {
30 RsaPssWithSha256 = 0x0101,
31 RsaPssWithSha512 = 0x0102,
32 RsaPkcs1V15WithSha256 = 0x0103,
33 RsaPkcs1V15WithSha512 = 0x0104,
34 EcdsaWithSha256 = 0x0201,
35 EcdsaWithSha512 = 0x0202,
36 DsaWithSha256 = 0x0301,
37 VerityRsaPkcs1V15WithSha256 = 0x0421,
38 VerityEcdsaWithSha256 = 0x0423,
39 VerityDsaWithSha256 = 0x0425,
40}
41
42impl Ord for SignatureAlgorithmID {
43 /// Ranks the signature algorithm according to the corresponding content
44 /// digest algorithm's rank.
45 fn cmp(&self, other: &Self) -> Ordering {
46 self.to_content_digest_algorithm().cmp(&other.to_content_digest_algorithm())
47 }
48}
49
50impl PartialOrd for SignatureAlgorithmID {
51 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
52 Some(self.cmp(other))
53 }
54}
55
56impl PartialEq for SignatureAlgorithmID {
57 fn eq(&self, other: &Self) -> bool {
58 self.cmp(other) == Ordering::Equal
59 }
60}
61
62impl SignatureAlgorithmID {
63 pub(crate) fn to_content_digest_algorithm(&self) -> ContentDigestAlgorithm {
64 match self {
65 SignatureAlgorithmID::RsaPssWithSha256
66 | SignatureAlgorithmID::RsaPkcs1V15WithSha256
67 | SignatureAlgorithmID::EcdsaWithSha256
68 | SignatureAlgorithmID::DsaWithSha256 => ContentDigestAlgorithm::ChunkedSha256,
69 SignatureAlgorithmID::RsaPssWithSha512
70 | SignatureAlgorithmID::RsaPkcs1V15WithSha512
71 | SignatureAlgorithmID::EcdsaWithSha512 => ContentDigestAlgorithm::ChunkedSha512,
72 SignatureAlgorithmID::VerityRsaPkcs1V15WithSha256
73 | SignatureAlgorithmID::VerityEcdsaWithSha256
74 | SignatureAlgorithmID::VerityDsaWithSha256 => {
75 ContentDigestAlgorithm::VerityChunkedSha256
76 }
77 }
78 }
79}
80
81/// The rank of the content digest algorithm in this enum is used to help pick
82/// v4 apk digest.
83/// According to APK Signature Scheme v4, [apk digest] is the first available
84/// content digest of the highest rank (rank N).
85///
86/// This rank was also used for step 3a of the v3 signature verification.
87///
88/// [apk digest]: https://source.android.com/docs/security/features/apksigning/v4#apk-digest
89/// [v3 verification]: https://source.android.com/docs/security/apksigning/v3#v3-verification
90#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
91pub(crate) enum ContentDigestAlgorithm {
92 ChunkedSha256 = 1,
93 VerityChunkedSha256,
94 ChunkedSha512,
95}
96
97impl ContentDigestAlgorithm {
98 pub(crate) fn new_message_digest(&self) -> Result<MessageDigest> {
99 match self {
100 ContentDigestAlgorithm::ChunkedSha256 => Ok(MessageDigest::sha256()),
101 ContentDigestAlgorithm::ChunkedSha512 => Ok(MessageDigest::sha512()),
102 ContentDigestAlgorithm::VerityChunkedSha256 => {
103 bail!("TODO(b/197052981): CONTENT_DIGEST_VERITY_CHUNKED_SHA256 is not implemented")
104 }
105 }
106 }
107}