• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #[cfg(feature = "multialg")]
25 use crate::KeyAlgorithm;
26 use alloc::{vec, vec::Vec};
27 #[cfg(feature = "multialg")]
28 use open_dice_cbor_bindgen::DiceContext_;
29 use open_dice_cbor_bindgen::{
30     DiceCoseSignAndEncodeSign1, DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed,
31     DicePrincipal, DiceSign, DiceVerify,
32 };
33 #[cfg(feature = "multialg")]
34 use std::ffi::c_void;
35 use std::ptr;
36 
37 /// Hashes the provided input using DICE's hash function `DiceHash`.
hash(input: &[u8]) -> Result<Hash>38 pub fn hash(input: &[u8]) -> Result<Hash> {
39     let mut output: Hash = [0; HASH_SIZE];
40     check_result(
41         // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output
42         // buffer. The first argument context is not used in this function.
43         unsafe {
44             DiceHash(
45                 ptr::null_mut(), // context
46                 input.as_ptr(),
47                 input.len(),
48                 output.as_mut_ptr(),
49             )
50         },
51         output.len(),
52     )?;
53     Ok(output)
54 }
55 
56 /// An implementation of HKDF-SHA512. Derives a key of `derived_key.len()` bytes from `ikm`, `salt`,
57 /// and `info`. The derived key is written to the `derived_key`.
kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()>58 pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
59     check_result(
60         // SAFETY: The function writes to the `derived_key`, within the given bounds, and only
61         // reads the input values. The first argument context is not used in this function.
62         unsafe {
63             DiceKdf(
64                 ptr::null_mut(), // context
65                 derived_key.len(),
66                 ikm.as_ptr(),
67                 ikm.len(),
68                 salt.as_ptr(),
69                 salt.len(),
70                 info.as_ptr(),
71                 info.len(),
72                 derived_key.as_mut_ptr(),
73             )
74         },
75         derived_key.len(),
76     )
77 }
78 
79 /// Deterministically generates a public and private key pair from `seed`.
80 /// Since this is deterministic, `seed` is as sensitive as a private key and can
81 /// be used directly as the private key.
keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, PrivateKey)>82 pub fn keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, PrivateKey)> {
83     let mut public_key = vec![0u8; VM_KEY_ALGORITHM.public_key_size()];
84     let mut private_key = PrivateKey::default();
85     // This function is used with an open-dice config that uses the same algorithms for the
86     // subject and authority. Therefore, the principal is irrelevant in this context as this
87     // function only derives the key pair cryptographically without caring about which
88     // principal it is for. Hence, we arbitrarily set it to `DicePrincipal::kDicePrincipalSubject`.
89     let principal = DicePrincipal::kDicePrincipalSubject;
90     check_result(
91         // SAFETY: The function writes to the `public_key` and `private_key` within the given
92         // bounds, and only reads the `seed`.
93         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
94         // and a null pointer otherwise.
95         unsafe {
96             DiceKeypairFromSeed(
97                 context(),
98                 principal,
99                 seed.as_ptr(),
100                 public_key.as_mut_ptr(),
101                 private_key.as_mut_ptr(),
102             )
103         },
104         public_key.len(),
105     )?;
106     Ok((public_key, private_key))
107 }
108 
109 /// Deterministically generates a public and private key pair from `seed` and `key_algorithm`.
110 /// Since this is deterministic, `seed` is as sensitive as a private key and can
111 /// be used directly as the private key.
112 #[cfg(feature = "multialg")]
keypair_from_seed_multialg( seed: &[u8; PRIVATE_KEY_SEED_SIZE], key_algorithm: KeyAlgorithm, ) -> Result<(Vec<u8>, PrivateKey)>113 pub fn keypair_from_seed_multialg(
114     seed: &[u8; PRIVATE_KEY_SEED_SIZE],
115     key_algorithm: KeyAlgorithm,
116 ) -> Result<(Vec<u8>, PrivateKey)> {
117     let mut public_key = vec![0u8; key_algorithm.public_key_size()];
118     let mut private_key = PrivateKey::default();
119     // This function is used with an open-dice config that uses the same algorithms for the
120     // subject and authority. Therefore, the principal is irrelevant in this context as this
121     // function only derives the key pair cryptographically without caring about which
122     // principal it is for. Hence, we arbitrarily set it to `DicePrincipal::kDicePrincipalSubject`.
123     let principal = DicePrincipal::kDicePrincipalSubject;
124     let context = DiceContext_ {
125         authority_algorithm: key_algorithm.into(),
126         subject_algorithm: key_algorithm.into(),
127     };
128     check_result(
129         // SAFETY: The function writes to the `public_key` and `private_key` within the given
130         // bounds, and only reads the `seed`.
131         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg
132         // open-dice.
133         unsafe {
134             DiceKeypairFromSeed(
135                 &context as *const DiceContext_ as *mut c_void,
136                 principal,
137                 seed.as_ptr(),
138                 public_key.as_mut_ptr(),
139                 private_key.as_mut_ptr(),
140             )
141         },
142         public_key.len(),
143     )?;
144     Ok((public_key, private_key))
145 }
146 
147 /// Derives the CDI_Leaf_Priv from the provided `dice_artifacts`.
148 ///
149 /// The corresponding public key is included in the leaf certificate of the DICE chain
150 /// contained in `dice_artifacts`.
151 ///
152 /// Refer to the following documentation for more information about CDI_Leaf_Priv:
153 ///
154 /// security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey>155 pub fn derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey> {
156     let cdi_priv_key_seed = derive_cdi_private_key_seed(dice_artifacts.cdi_attest())?;
157     let (_, private_key) = keypair_from_seed(cdi_priv_key_seed.as_array())?;
158     Ok(private_key)
159 }
160 
161 /// Multialg variant of `derive_cdi_leaf_priv`.
162 #[cfg(feature = "multialg")]
derive_cdi_leaf_priv_multialg( dice_artifacts: &dyn DiceArtifacts, key_algorithm: KeyAlgorithm, ) -> Result<PrivateKey>163 pub fn derive_cdi_leaf_priv_multialg(
164     dice_artifacts: &dyn DiceArtifacts,
165     key_algorithm: KeyAlgorithm,
166 ) -> Result<PrivateKey> {
167     let cdi_priv_key_seed = derive_cdi_private_key_seed(dice_artifacts.cdi_attest())?;
168     let (_, private_key) = keypair_from_seed_multialg(cdi_priv_key_seed.as_array(), key_algorithm)?;
169     Ok(private_key)
170 }
171 
172 /// Signs the `message` with the given `private_key` using `DiceSign`.
sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>>173 pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>> {
174     let mut signature = vec![0u8; VM_KEY_ALGORITHM.signature_size()];
175     check_result(
176         // SAFETY: The function writes to the `signature` within the given bounds, and only reads
177         // the message and the private key.
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             DiceSign(
182                 context(),
183                 message.as_ptr(),
184                 message.len(),
185                 private_key.as_ptr(),
186                 signature.as_mut_ptr(),
187             )
188         },
189         signature.len(),
190     )?;
191     Ok(signature)
192 }
193 
194 /// Signs the `message` with the given `private_key` and places a `CoseSign1` encoded
195 /// object in `encoded_signature`. Uses `DiceCoseSignAndEncodeSign1`.
196 ///
197 /// Returns the actual size of encoded_signature on success.
sign_cose_sign1( message: &[u8], aad: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE], encoded_signature: &mut [u8], ) -> Result<usize>198 pub fn sign_cose_sign1(
199     message: &[u8],
200     aad: &[u8],
201     private_key: &[u8; PRIVATE_KEY_SIZE],
202     encoded_signature: &mut [u8],
203 ) -> Result<usize> {
204     let mut encoded_signature_actual_size = 0;
205 
206     check_result(
207         // SAFETY: The function writes to `encoded_signature` and `encoded_signature_actual_size`
208         // within the given bounds. It only reads `message`, `aad`, and `private_key` within their
209         // given bounds.
210         //
211         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
212         // and a null pointer otherwise.
213         unsafe {
214             DiceCoseSignAndEncodeSign1(
215                 context(),
216                 message.as_ptr(),
217                 message.len(),
218                 aad.as_ptr(),
219                 aad.len(),
220                 private_key.as_ptr(),
221                 encoded_signature.len(),
222                 encoded_signature.as_mut_ptr(),
223                 &mut encoded_signature_actual_size,
224             )
225         },
226         encoded_signature_actual_size,
227     )?;
228     Ok(encoded_signature_actual_size)
229 }
230 
231 /// Multialg variant of `sign_cose_sign1`.
232 #[cfg(feature = "multialg")]
sign_cose_sign1_multialg( message: &[u8], aad: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE], encoded_signature: &mut [u8], key_algorithm: KeyAlgorithm, ) -> Result<usize>233 pub fn sign_cose_sign1_multialg(
234     message: &[u8],
235     aad: &[u8],
236     private_key: &[u8; PRIVATE_KEY_SIZE],
237     encoded_signature: &mut [u8],
238     key_algorithm: KeyAlgorithm,
239 ) -> Result<usize> {
240     let mut encoded_signature_actual_size = 0;
241     let context = DiceContext_ {
242         authority_algorithm: key_algorithm.into(),
243         subject_algorithm: key_algorithm.into(),
244     };
245     check_result(
246         // SAFETY: The function writes to `encoded_signature` and `encoded_signature_actual_size`
247         // within the given bounds. It only reads `message`, `aad`, and `private_key` within their
248         // given bounds.
249         //
250         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg
251         // open-dice.
252         unsafe {
253             DiceCoseSignAndEncodeSign1(
254                 &context as *const DiceContext_ as *mut c_void,
255                 message.as_ptr(),
256                 message.len(),
257                 aad.as_ptr(),
258                 aad.len(),
259                 private_key.as_ptr(),
260                 encoded_signature.len(),
261                 encoded_signature.as_mut_ptr(),
262                 &mut encoded_signature_actual_size,
263             )
264         },
265         encoded_signature_actual_size,
266     )?;
267     Ok(encoded_signature_actual_size)
268 }
269 
270 /// Signs the `message` with a private key derived from the given `dice_artifacts`
271 /// CDI Attest. On success, places a `CoseSign1` encoded object in `encoded_signature`.
272 /// Uses `DiceCoseSignAndEncodeSign1`.
273 ///
274 /// Returns the actual size of encoded_signature on success.
sign_cose_sign1_with_cdi_leaf_priv( message: &[u8], aad: &[u8], dice_artifacts: &dyn DiceArtifacts, encoded_signature: &mut [u8], ) -> Result<usize>275 pub fn sign_cose_sign1_with_cdi_leaf_priv(
276     message: &[u8],
277     aad: &[u8],
278     dice_artifacts: &dyn DiceArtifacts,
279     encoded_signature: &mut [u8],
280 ) -> Result<usize> {
281     let private_key = derive_cdi_leaf_priv(dice_artifacts)?;
282     sign_cose_sign1(message, aad, private_key.as_array(), encoded_signature)
283 }
284 
285 /// Multialg variant of `sign_cose_sign1_with_cdi_leaf_priv`.
286 #[cfg(feature = "multialg")]
sign_cose_sign1_with_cdi_leaf_priv_multialg( message: &[u8], aad: &[u8], dice_artifacts: &dyn DiceArtifacts, encoded_signature: &mut [u8], key_algorithm: KeyAlgorithm, ) -> Result<usize>287 pub fn sign_cose_sign1_with_cdi_leaf_priv_multialg(
288     message: &[u8],
289     aad: &[u8],
290     dice_artifacts: &dyn DiceArtifacts,
291     encoded_signature: &mut [u8],
292     key_algorithm: KeyAlgorithm,
293 ) -> Result<usize> {
294     let private_key = derive_cdi_leaf_priv_multialg(dice_artifacts, key_algorithm)?;
295     sign_cose_sign1_multialg(message, aad, private_key.as_array(), encoded_signature, key_algorithm)
296 }
297 
298 /// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
verify(message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<()>299 pub fn verify(message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<()> {
300     if signature.len() != VM_KEY_ALGORITHM.signature_size()
301         || public_key.len() != VM_KEY_ALGORITHM.public_key_size()
302     {
303         return Err(DiceError::InvalidInput);
304     }
305     check_result(
306         // SAFETY: only reads the messages, signature and public key as constant values.
307         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
308         // and a null pointer otherwise.
309         unsafe {
310             DiceVerify(
311                 context(),
312                 message.as_ptr(),
313                 message.len(),
314                 signature.as_ptr(),
315                 public_key.as_ptr(),
316             )
317         },
318         0,
319     )
320 }
321 
322 /// Multialg variant of `verify`.
323 #[cfg(feature = "multialg")]
verify_multialg( message: &[u8], signature: &[u8], public_key: &[u8], key_algorithm: KeyAlgorithm, ) -> Result<()>324 pub fn verify_multialg(
325     message: &[u8],
326     signature: &[u8],
327     public_key: &[u8],
328     key_algorithm: KeyAlgorithm,
329 ) -> Result<()> {
330     if signature.len() != key_algorithm.signature_size()
331         || public_key.len() != key_algorithm.public_key_size()
332     {
333         return Err(DiceError::InvalidInput);
334     }
335     let context = DiceContext_ {
336         authority_algorithm: key_algorithm.into(),
337         subject_algorithm: key_algorithm.into(),
338     };
339     check_result(
340         // SAFETY: only reads the messages, signature and public key as constant values.
341         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg
342         // open-dice.
343         unsafe {
344             DiceVerify(
345                 &context as *const DiceContext_ as *mut c_void,
346                 message.as_ptr(),
347                 message.len(),
348                 signature.as_ptr(),
349                 public_key.as_ptr(),
350             )
351         },
352         0,
353     )
354 }
355 
356 /// Generates an X.509 certificate from the given `subject_private_key_seed` and
357 /// `input_values`, and signed by `authority_private_key_seed`.
358 /// The subject private key seed is supplied here so the implementation can choose
359 /// between asymmetric mechanisms, for example ECDSA vs Ed25519.
360 /// 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>361 pub fn generate_certificate(
362     subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
363     authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
364     input_values: &InputValues,
365     certificate: &mut [u8],
366 ) -> Result<usize> {
367     let mut certificate_actual_size = 0;
368     check_result(
369         // SAFETY: The function writes to the `certificate` within the given bounds, and only reads
370         // the input values and the key seeds.
371         // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
372         // and a null pointer otherwise.
373         unsafe {
374             DiceGenerateCertificate(
375                 context(),
376                 subject_private_key_seed.as_ptr(),
377                 authority_private_key_seed.as_ptr(),
378                 input_values.as_ptr(),
379                 certificate.len(),
380                 certificate.as_mut_ptr(),
381                 &mut certificate_actual_size,
382             )
383         },
384         certificate_actual_size,
385     )?;
386     Ok(certificate_actual_size)
387 }
388