1 // Copyright 2023, 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 mirrors the content in open-dice/include/dice/ops.h
16 //! It contains the set of functions that implement various operations that the
17 //! main DICE functions depend on.
18 
19 use crate::dice::{
20     context, derive_cdi_private_key_seed, DiceArtifacts, Hash, InputValues, PrivateKey, HASH_SIZE,
21     PRIVATE_KEY_SEED_SIZE, PRIVATE_KEY_SIZE, VM_KEY_ALGORITHM,
22 };
23 use crate::error::{check_result, DiceError, Result};
24 use alloc::{vec, vec::Vec};
25 use open_dice_cbor_bindgen::{
26     DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed, DicePrincipal, DiceSign,
27     DiceVerify,
28 };
29 use std::ptr;
30 
31 /// Hashes the provided input using DICE's hash function `DiceHash`.
hash(input: &[u8]) -> Result<Hash>32 pub fn hash(input: &[u8]) -> Result<Hash> {
33     let mut output: Hash = [0; HASH_SIZE];
34     check_result(
35         // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output
36         // buffer. The first argument context is not used in this function.
37         unsafe {
38             DiceHash(
39                 ptr::null_mut(), // context
40                 input.as_ptr(),
41                 input.len(),
42                 output.as_mut_ptr(),
43             )
44         },
45         output.len(),
46     )?;
47     Ok(output)
48 }
49 
50 /// An implementation of HKDF-SHA512. Derives a key of `derived_key.len()` bytes from `ikm`, `salt`,
51 /// and `info`. The derived key is written to the `derived_key`.
kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()>52 pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
53     check_result(
54         // SAFETY: The function writes to the `derived_key`, within the given bounds, and only
55         // reads the input values. The first argument context is not used in this function.
56         unsafe {
57             DiceKdf(
58                 ptr::null_mut(), // context
59                 derived_key.len(),
60                 ikm.as_ptr(),
61                 ikm.len(),
62                 salt.as_ptr(),
63                 salt.len(),
64                 info.as_ptr(),
65                 info.len(),
66                 derived_key.as_mut_ptr(),
67             )
68         },
69         derived_key.len(),
70     )
71 }
72 
73 /// Deterministically generates a public and private key pair from `seed`.
74 /// Since this is deterministic, `seed` is as sensitive as a private key and can
75 /// be used directly as the private key.
keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, PrivateKey)>76 pub fn keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, PrivateKey)> {
77     let mut public_key = vec![0u8; VM_KEY_ALGORITHM.public_key_size()];
78     let mut private_key = PrivateKey::default();
79     // This function is used with an open-dice config that uses the same algorithms for the
80     // subject and authority. Therefore, the principal is irrelevant in this context as this
81     // function only derives the key pair cryptographically without caring about which
82     // principal it is for. Hence, we arbitrarily set it to `DicePrincipal::kDicePrincipalSubject`.
83     let principal = DicePrincipal::kDicePrincipalSubject;
84     check_result(
85         // SAFETY: The function writes to the `public_key` and `private_key` within the given
86         // bounds, and only reads the `seed`.
87         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
88         // and a null pointer otherwise.
89         unsafe {
90             DiceKeypairFromSeed(
91                 context(),
92                 principal,
93                 seed.as_ptr(),
94                 public_key.as_mut_ptr(),
95                 private_key.as_mut_ptr(),
96             )
97         },
98         public_key.len(),
99     )?;
100     Ok((public_key, private_key))
101 }
102 
103 /// Derives the CDI_Leaf_Priv from the provided `dice_artifacts`.
104 ///
105 /// The corresponding public key is included in the leaf certificate of the DICE chain
106 /// contained in `dice_artifacts`.
107 ///
108 /// Refer to the following documentation for more information about CDI_Leaf_Priv:
109 ///
110 /// security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey>111 pub fn derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey> {
112     let cdi_priv_key_seed = derive_cdi_private_key_seed(dice_artifacts.cdi_attest())?;
113     let (_, private_key) = keypair_from_seed(cdi_priv_key_seed.as_array())?;
114     Ok(private_key)
115 }
116 
117 /// Signs the `message` with the give `private_key` using `DiceSign`.
sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>>118 pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>> {
119     let mut signature = vec![0u8; VM_KEY_ALGORITHM.signature_size()];
120     check_result(
121         // SAFETY: The function writes to the `signature` within the given bounds, and only reads
122         // the message and the private key.
123         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
124         // and a null pointer otherwise.
125         unsafe {
126             DiceSign(
127                 context(),
128                 message.as_ptr(),
129                 message.len(),
130                 private_key.as_ptr(),
131                 signature.as_mut_ptr(),
132             )
133         },
134         signature.len(),
135     )?;
136     Ok(signature)
137 }
138 
139 /// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
verify(message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<()>140 pub fn verify(message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<()> {
141     if signature.len() != VM_KEY_ALGORITHM.signature_size()
142         || public_key.len() != VM_KEY_ALGORITHM.public_key_size()
143     {
144         return Err(DiceError::InvalidInput);
145     }
146     check_result(
147         // SAFETY: only reads the messages, signature and public key as constant values.
148         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
149         // and a null pointer otherwise.
150         unsafe {
151             DiceVerify(
152                 context(),
153                 message.as_ptr(),
154                 message.len(),
155                 signature.as_ptr(),
156                 public_key.as_ptr(),
157             )
158         },
159         0,
160     )
161 }
162 
163 /// Generates an X.509 certificate from the given `subject_private_key_seed` and
164 /// `input_values`, and signed by `authority_private_key_seed`.
165 /// The subject private key seed is supplied here so the implementation can choose
166 /// between asymmetric mechanisms, for example ECDSA vs Ed25519.
167 /// Returns the actual size of the generated certificate.
generate_certificate( subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE], authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE], input_values: &InputValues, certificate: &mut [u8], ) -> Result<usize>168 pub fn generate_certificate(
169     subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
170     authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
171     input_values: &InputValues,
172     certificate: &mut [u8],
173 ) -> Result<usize> {
174     let mut certificate_actual_size = 0;
175     check_result(
176         // SAFETY: The function writes to the `certificate` within the given bounds, and only reads
177         // the input values and the key seeds.
178         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
179         // and a null pointer otherwise.
180         unsafe {
181             DiceGenerateCertificate(
182                 context(),
183                 subject_private_key_seed.as_ptr(),
184                 authority_private_key_seed.as_ptr(),
185                 input_values.as_ptr(),
186                 certificate.len(),
187                 certificate.as_mut_ptr(),
188                 &mut certificate_actual_size,
189             )
190         },
191         certificate_actual_size,
192     )?;
193     Ok(certificate_actual_size)
194 }
195