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     derive_cdi_private_key_seed, DiceArtifacts, Hash, InputValues, PrivateKey, PublicKey,
21     Signature, HASH_SIZE, PRIVATE_KEY_SEED_SIZE, PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE, SIGNATURE_SIZE,
22 };
23 use crate::error::{check_result, Result};
24 use open_dice_cbor_bindgen::{
25     DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed, DiceSign, DiceVerify,
26 };
27 use std::ptr;
28 
29 /// Hashes the provided input using DICE's hash function `DiceHash`.
hash(input: &[u8]) -> Result<Hash>30 pub fn hash(input: &[u8]) -> Result<Hash> {
31     let mut output: Hash = [0; HASH_SIZE];
32     check_result(
33         // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output
34         // buffer. The first argument context is not used in this function.
35         unsafe {
36             DiceHash(
37                 ptr::null_mut(), // context
38                 input.as_ptr(),
39                 input.len(),
40                 output.as_mut_ptr(),
41             )
42         },
43         output.len(),
44     )?;
45     Ok(output)
46 }
47 
48 /// An implementation of HKDF-SHA512. Derives a key of `derived_key.len()` bytes from `ikm`, `salt`,
49 /// and `info`. The derived key is written to the `derived_key`.
kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()>50 pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
51     check_result(
52         // SAFETY: The function writes to the `derived_key`, within the given bounds, and only
53         // reads the input values. The first argument context is not used in this function.
54         unsafe {
55             DiceKdf(
56                 ptr::null_mut(), // context
57                 derived_key.len(),
58                 ikm.as_ptr(),
59                 ikm.len(),
60                 salt.as_ptr(),
61                 salt.len(),
62                 info.as_ptr(),
63                 info.len(),
64                 derived_key.as_mut_ptr(),
65             )
66         },
67         derived_key.len(),
68     )
69 }
70 
71 /// Deterministically generates a public and private key pair from `seed`.
72 /// Since this is deterministic, `seed` is as sensitive as a private key and can
73 /// be used directly as the private key.
keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(PublicKey, PrivateKey)>74 pub fn keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(PublicKey, PrivateKey)> {
75     let mut public_key = [0u8; PUBLIC_KEY_SIZE];
76     let mut private_key = PrivateKey::default();
77     check_result(
78         // SAFETY: The function writes to the `public_key` and `private_key` within the given
79         // bounds, and only reads the `seed`. The first argument context is not used in this
80         // function.
81         unsafe {
82             DiceKeypairFromSeed(
83                 ptr::null_mut(), // context
84                 seed.as_ptr(),
85                 public_key.as_mut_ptr(),
86                 private_key.as_mut_ptr(),
87             )
88         },
89         public_key.len(),
90     )?;
91     Ok((public_key, private_key))
92 }
93 
94 /// Derives the CDI_Leaf_Priv from the provided `dice_artifacts`.
95 ///
96 /// The corresponding public key is included in the leaf certificate of the DICE chain
97 /// contained in `dice_artifacts`.
98 ///
99 /// Refer to the following documentation for more information about CDI_Leaf_Priv:
100 ///
101 /// security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey>102 pub fn derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey> {
103     let cdi_priv_key_seed = derive_cdi_private_key_seed(dice_artifacts.cdi_attest())?;
104     let (_, private_key) = keypair_from_seed(cdi_priv_key_seed.as_array())?;
105     Ok(private_key)
106 }
107 
108 /// Signs the `message` with the give `private_key` using `DiceSign`.
sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature>109 pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature> {
110     let mut signature = [0u8; SIGNATURE_SIZE];
111     check_result(
112         // SAFETY: The function writes to the `signature` within the given bounds, and only reads
113         // the message and the private key. The first argument context is not used in this
114         // function.
115         unsafe {
116             DiceSign(
117                 ptr::null_mut(), // context
118                 message.as_ptr(),
119                 message.len(),
120                 private_key.as_ptr(),
121                 signature.as_mut_ptr(),
122             )
123         },
124         signature.len(),
125     )?;
126     Ok(signature)
127 }
128 
129 /// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()>130 pub fn verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()> {
131     check_result(
132         // SAFETY: only reads the messages, signature and public key as constant values.
133         // The first argument context is not used in this function.
134         unsafe {
135             DiceVerify(
136                 ptr::null_mut(), // context
137                 message.as_ptr(),
138                 message.len(),
139                 signature.as_ptr(),
140                 public_key.as_ptr(),
141             )
142         },
143         0,
144     )
145 }
146 
147 /// Generates an X.509 certificate from the given `subject_private_key_seed` and
148 /// `input_values`, and signed by `authority_private_key_seed`.
149 /// The subject private key seed is supplied here so the implementation can choose
150 /// between asymmetric mechanisms, for example ECDSA vs Ed25519.
151 /// 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>152 pub fn generate_certificate(
153     subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
154     authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
155     input_values: &InputValues,
156     certificate: &mut [u8],
157 ) -> Result<usize> {
158     let mut certificate_actual_size = 0;
159     check_result(
160         // SAFETY: The function writes to the `certificate` within the given bounds, and only reads
161         // the input values and the key seeds. The first argument context is not used in this
162         // function.
163         unsafe {
164             DiceGenerateCertificate(
165                 ptr::null_mut(), // context
166                 subject_private_key_seed.as_ptr(),
167                 authority_private_key_seed.as_ptr(),
168                 input_values.as_ptr(),
169                 certificate.len(),
170                 certificate.as_mut_ptr(),
171                 &mut certificate_actual_size,
172             )
173         },
174         certificate_actual_size,
175     )?;
176     Ok(certificate_actual_size)
177 }
178