• 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     Hash, InputValues, PrivateKey, PublicKey, Signature, HASH_SIZE, PRIVATE_KEY_SEED_SIZE,
21     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     // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output buffer.
33     // The first argument context is not used in this function.
34     check_result(unsafe {
35         DiceHash(
36             ptr::null_mut(), // context
37             input.as_ptr(),
38             input.len(),
39             output.as_mut_ptr(),
40         )
41     })?;
42     Ok(output)
43 }
44 
45 /// An implementation of HKDF-SHA512. Derives a key of `derived_key.len()` bytes from `ikm`, `salt`,
46 /// and `info`. The derived key is written to the `derived_key`.
kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()>47 pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
48     // SAFETY: The function writes to the `derived_key`, within the given bounds, and only reads the
49     // input values. The first argument context is not used in this function.
50     check_result(unsafe {
51         DiceKdf(
52             ptr::null_mut(), // context
53             derived_key.len(),
54             ikm.as_ptr(),
55             ikm.len(),
56             salt.as_ptr(),
57             salt.len(),
58             info.as_ptr(),
59             info.len(),
60             derived_key.as_mut_ptr(),
61         )
62     })
63 }
64 
65 /// Deterministically generates a public and private key pair from `seed`.
66 /// Since this is deterministic, `seed` is as sensitive as a private key and can
67 /// be used directly as the private key.
keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(PublicKey, PrivateKey)>68 pub fn keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(PublicKey, PrivateKey)> {
69     let mut public_key = [0u8; PUBLIC_KEY_SIZE];
70     let mut private_key = PrivateKey::default();
71     // SAFETY: The function writes to the `public_key` and `private_key` within the given bounds,
72     // and only reads the `seed`. The first argument context is not used in this function.
73     check_result(unsafe {
74         DiceKeypairFromSeed(
75             ptr::null_mut(), // context
76             seed.as_ptr(),
77             public_key.as_mut_ptr(),
78             private_key.as_mut_ptr(),
79         )
80     })?;
81     Ok((public_key, private_key))
82 }
83 
84 /// Signs the `message` with the give `private_key` using `DiceSign`.
sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature>85 pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature> {
86     let mut signature = [0u8; SIGNATURE_SIZE];
87     // SAFETY: The function writes to the `signature` within the given bounds, and only reads the
88     // message and the private key. The first argument context is not used in this function.
89     check_result(unsafe {
90         DiceSign(
91             ptr::null_mut(), // context
92             message.as_ptr(),
93             message.len(),
94             private_key.as_ptr(),
95             signature.as_mut_ptr(),
96         )
97     })?;
98     Ok(signature)
99 }
100 
101 /// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()>102 pub fn verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()> {
103     // SAFETY: only reads the messages, signature and public key as constant values.
104     // The first argument context is not used in this function.
105     check_result(unsafe {
106         DiceVerify(
107             ptr::null_mut(), // context
108             message.as_ptr(),
109             message.len(),
110             signature.as_ptr(),
111             public_key.as_ptr(),
112         )
113     })
114 }
115 
116 /// Generates an X.509 certificate from the given `subject_private_key_seed` and
117 /// `input_values`, and signed by `authority_private_key_seed`.
118 /// The subject private key seed is supplied here so the implementation can choose
119 /// between asymmetric mechanisms, for example ECDSA vs Ed25519.
120 /// 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>121 pub fn generate_certificate(
122     subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
123     authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
124     input_values: &InputValues,
125     certificate: &mut [u8],
126 ) -> Result<usize> {
127     let mut certificate_actual_size = 0;
128     // SAFETY: The function writes to the `certificate` within the given bounds, and only reads the
129     // input values and the key seeds. The first argument context is not used in this function.
130     check_result(unsafe {
131         DiceGenerateCertificate(
132             ptr::null_mut(), // context
133             subject_private_key_seed.as_ptr(),
134             authority_private_key_seed.as_ptr(),
135             input_values.as_ptr(),
136             certificate.len(),
137             certificate.as_mut_ptr(),
138             &mut certificate_actual_size,
139         )
140     })?;
141     Ok(certificate_actual_size)
142 }
143