blob: 6398f31c250c1467000556ad70e6b45862871efc [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 Nyamagouddc6fb232021-12-08 21:27:15 +000033/// Vold namespace.
34pub const SELINUX_VOLD_NAMESPACE: i64 = 100;
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000035
Rajesh Nyamagoudfa7c0f12021-12-02 17:15:48 +000036/// SU context.
37pub const TARGET_SU_CTX: &str = "u:r:su:s0";
38
39/// Vold context
40pub const TARGET_VOLD_CTX: &str = "u:r:vold:s0";
41
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000042/// To map Keystore errors.
43#[derive(thiserror::Error, Debug, Eq, PartialEq)]
44pub enum Error {
45 /// Keystore2 error code
46 #[error("ResponseCode {0:?}")]
47 Rc(ResponseCode),
48 /// Keymint error code
49 #[error("ErrorCode {0:?}")]
50 Km(ErrorCode),
51 /// Exception
52 #[error("Binder exception {0:?}")]
53 Binder(ExceptionCode),
54}
55
56/// Keystore2 error mapping.
57pub fn map_ks_error<T>(r: BinderResult<T>) -> Result<T, Error> {
58 r.map_err(|s| {
59 match s.exception_code() {
60 ExceptionCode::SERVICE_SPECIFIC => {
61 match s.service_specific_error() {
62 se if se < 0 => {
63 // Negative service specific errors are KM error codes.
64 Error::Km(ErrorCode(se))
65 }
66 se => {
67 // Positive service specific errors are KS response codes.
68 Error::Rc(ResponseCode(se))
69 }
70 }
71 }
72 // We create `Error::Binder` to preserve the exception code
73 // for logging.
74 e_code => Error::Binder(e_code),
75 }
76 })
77}
78
79/// Generate EC Key using given security level and domain with below key parameters and
80/// optionally allow the generated key to be attested with factory provisioned attest key using
81/// given challenge and application id -
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000082/// Purposes: SIGN and VERIFY
83/// Digest: SHA_2_256
84/// Curve: P_256
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000085pub fn generate_ec_p256_signing_key(
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000086 sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000087 domain: Domain,
88 nspace: i64,
89 alias: Option<String>,
90 att_challenge: Option<&[u8]>,
91 att_app_id: Option<&[u8]>,
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000092) -> binder::Result<KeyMetadata> {
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000093 let mut key_attest = false;
94 let mut gen_params = AuthSetBuilder::new()
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000095 .algorithm(Algorithm::EC)
96 .purpose(KeyPurpose::SIGN)
97 .purpose(KeyPurpose::VERIFY)
98 .digest(Digest::SHA_2_256)
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000099 .ec_curve(EcCurve::P_256);
100
101 if let Some(challenge) = att_challenge {
102 key_attest = true;
103 gen_params = gen_params.clone().attestation_challenge(challenge.to_vec());
104 }
105
106 if let Some(app_id) = att_app_id {
107 key_attest = true;
108 gen_params = gen_params.clone().attestation_app_id(app_id.to_vec());
109 }
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000110
111 match sec_level.generateKey(
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +0000112 &KeyDescriptor { domain, nspace, alias, blob: None },
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000113 None,
114 &gen_params,
115 0,
116 b"entropy",
117 ) {
118 Ok(key_metadata) => {
119 assert!(key_metadata.certificate.is_some());
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +0000120 if key_attest {
121 assert!(key_metadata.certificateChain.is_some());
122 }
123 if domain == Domain::BLOB {
124 assert!(key_metadata.key.blob.is_some());
125 }
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000126
127 Ok(key_metadata)
128 }
129 Err(e) => Err(e),
130 }
131}