blob: f8628eec4279d47aa647f4e51b31db9fa1039a1f [file] [log] [blame]
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +00001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! This module implements test utils to generate various types of keys.
16
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000017use anyhow::Result;
18
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000019use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000020 Algorithm::Algorithm, Digest::Digest, EcCurve::EcCurve, ErrorCode::ErrorCode,
21 KeyPurpose::KeyPurpose,
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000022};
23use android_system_keystore2::aidl::android::system::keystore2::{
24 Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000025 KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000026};
27
28use crate::authorizations::AuthSetBuilder;
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000029use android_system_keystore2::binder::{ExceptionCode, Result as BinderResult};
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000030
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000031/// Shell namespace.
32pub const SELINUX_SHELL_NAMESPACE: i64 = 1;
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000033
Rajesh Nyamagoudfa7c0f12021-12-02 17:15:48 +000034/// SU context.
35pub const TARGET_SU_CTX: &str = "u:r:su:s0";
36
37/// Vold context
38pub const TARGET_VOLD_CTX: &str = "u:r:vold:s0";
39
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000040/// To map Keystore errors.
41#[derive(thiserror::Error, Debug, Eq, PartialEq)]
42pub enum Error {
43 /// Keystore2 error code
44 #[error("ResponseCode {0:?}")]
45 Rc(ResponseCode),
46 /// Keymint error code
47 #[error("ErrorCode {0:?}")]
48 Km(ErrorCode),
49 /// Exception
50 #[error("Binder exception {0:?}")]
51 Binder(ExceptionCode),
52}
53
54/// Keystore2 error mapping.
55pub fn map_ks_error<T>(r: BinderResult<T>) -> Result<T, Error> {
56 r.map_err(|s| {
57 match s.exception_code() {
58 ExceptionCode::SERVICE_SPECIFIC => {
59 match s.service_specific_error() {
60 se if se < 0 => {
61 // Negative service specific errors are KM error codes.
62 Error::Km(ErrorCode(se))
63 }
64 se => {
65 // Positive service specific errors are KS response codes.
66 Error::Rc(ResponseCode(se))
67 }
68 }
69 }
70 // We create `Error::Binder` to preserve the exception code
71 // for logging.
72 e_code => Error::Binder(e_code),
73 }
74 })
75}
76
77/// Generate EC Key using given security level and domain with below key parameters and
78/// optionally allow the generated key to be attested with factory provisioned attest key using
79/// given challenge and application id -
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000080/// Purposes: SIGN and VERIFY
81/// Digest: SHA_2_256
82/// Curve: P_256
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000083pub fn generate_ec_p256_signing_key(
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000084 sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000085 domain: Domain,
86 nspace: i64,
87 alias: Option<String>,
88 att_challenge: Option<&[u8]>,
89 att_app_id: Option<&[u8]>,
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000090) -> binder::Result<KeyMetadata> {
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000091 let mut key_attest = false;
92 let mut gen_params = AuthSetBuilder::new()
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000093 .algorithm(Algorithm::EC)
94 .purpose(KeyPurpose::SIGN)
95 .purpose(KeyPurpose::VERIFY)
96 .digest(Digest::SHA_2_256)
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000097 .ec_curve(EcCurve::P_256);
98
99 if let Some(challenge) = att_challenge {
100 key_attest = true;
101 gen_params = gen_params.clone().attestation_challenge(challenge.to_vec());
102 }
103
104 if let Some(app_id) = att_app_id {
105 key_attest = true;
106 gen_params = gen_params.clone().attestation_app_id(app_id.to_vec());
107 }
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000108
109 match sec_level.generateKey(
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +0000110 &KeyDescriptor { domain, nspace, alias, blob: None },
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000111 None,
112 &gen_params,
113 0,
114 b"entropy",
115 ) {
116 Ok(key_metadata) => {
117 assert!(key_metadata.certificate.is_some());
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +0000118 if key_attest {
119 assert!(key_metadata.certificateChain.is_some());
120 }
121 if domain == Domain::BLOB {
122 assert!(key_metadata.key.blob.is_some());
123 }
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000124
125 Ok(key_metadata)
126 }
127 Err(e) => Err(e),
128 }
129}