blob: d917fa1dc32f24f5622cd07c6eb4a2815aa33d67 [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 Nyamagoudb881d512021-12-10 00:33:15 +000034/// To map Keystore errors.
35#[derive(thiserror::Error, Debug, Eq, PartialEq)]
36pub enum Error {
37 /// Keystore2 error code
38 #[error("ResponseCode {0:?}")]
39 Rc(ResponseCode),
40 /// Keymint error code
41 #[error("ErrorCode {0:?}")]
42 Km(ErrorCode),
43 /// Exception
44 #[error("Binder exception {0:?}")]
45 Binder(ExceptionCode),
46}
47
48/// Keystore2 error mapping.
49pub fn map_ks_error<T>(r: BinderResult<T>) -> Result<T, Error> {
50 r.map_err(|s| {
51 match s.exception_code() {
52 ExceptionCode::SERVICE_SPECIFIC => {
53 match s.service_specific_error() {
54 se if se < 0 => {
55 // Negative service specific errors are KM error codes.
56 Error::Km(ErrorCode(se))
57 }
58 se => {
59 // Positive service specific errors are KS response codes.
60 Error::Rc(ResponseCode(se))
61 }
62 }
63 }
64 // We create `Error::Binder` to preserve the exception code
65 // for logging.
66 e_code => Error::Binder(e_code),
67 }
68 })
69}
70
71/// Generate EC Key using given security level and domain with below key parameters and
72/// optionally allow the generated key to be attested with factory provisioned attest key using
73/// given challenge and application id -
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000074/// Purposes: SIGN and VERIFY
75/// Digest: SHA_2_256
76/// Curve: P_256
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000077pub fn generate_ec_p256_signing_key(
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000078 sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000079 domain: Domain,
80 nspace: i64,
81 alias: Option<String>,
82 att_challenge: Option<&[u8]>,
83 att_app_id: Option<&[u8]>,
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000084) -> binder::Result<KeyMetadata> {
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000085 let mut key_attest = false;
86 let mut gen_params = AuthSetBuilder::new()
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +000087 .algorithm(Algorithm::EC)
88 .purpose(KeyPurpose::SIGN)
89 .purpose(KeyPurpose::VERIFY)
90 .digest(Digest::SHA_2_256)
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +000091 .ec_curve(EcCurve::P_256);
92
93 if let Some(challenge) = att_challenge {
94 key_attest = true;
95 gen_params = gen_params.clone().attestation_challenge(challenge.to_vec());
96 }
97
98 if let Some(app_id) = att_app_id {
99 key_attest = true;
100 gen_params = gen_params.clone().attestation_app_id(app_id.to_vec());
101 }
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000102
103 match sec_level.generateKey(
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +0000104 &KeyDescriptor { domain, nspace, alias, blob: None },
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000105 None,
106 &gen_params,
107 0,
108 b"entropy",
109 ) {
110 Ok(key_metadata) => {
111 assert!(key_metadata.certificate.is_some());
Rajesh Nyamagoudb881d512021-12-10 00:33:15 +0000112 if key_attest {
113 assert!(key_metadata.certificateChain.is_some());
114 }
115 if domain == Domain::BLOB {
116 assert!(key_metadata.key.blob.is_some());
117 }
Rajesh Nyamagoud901386c2022-03-21 20:35:18 +0000118
119 Ok(key_metadata)
120 }
121 Err(e) => Err(e),
122 }
123}