blob: fe981dfeb18b72704da84912206c121fff996f46 [file] [log] [blame]
Alice Wang24954b42023-02-06 10:03:45 +00001// 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
Alice Wang8722d9e2023-02-13 14:56:56 +000019use crate::dice::{
Alice Wangfd9ebcf2023-10-12 15:07:47 +000020 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,
Alice Wang8722d9e2023-02-13 14:56:56 +000022};
Alice Wang24954b42023-02-06 10:03:45 +000023use crate::error::{check_result, Result};
Alice Wangf59662d2023-02-10 16:07:56 +000024use open_dice_cbor_bindgen::{
25 DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed, DiceSign, DiceVerify,
26};
Alice Wang24954b42023-02-06 10:03:45 +000027use std::ptr;
28
29/// Hashes the provided input using DICE's hash function `DiceHash`.
30pub fn hash(input: &[u8]) -> Result<Hash> {
31 let mut output: Hash = [0; HASH_SIZE];
Alice Wangef999242023-05-22 11:14:59 +000032 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +010033 // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output buffer.
34 // The first argument context is not used in this function.
Alice Wangef999242023-05-22 11:14:59 +000035 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 )?;
Alice Wang24954b42023-02-06 10:03:45 +000045 Ok(output)
46}
Alice Wang6ef44bc2023-02-08 12:08:32 +000047
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`.
50pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
Alice Wangef999242023-05-22 11:14:59 +000051 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +010052 // SAFETY: The function writes to the `derived_key`, within the given bounds, and only reads
53 // the input values. The first argument context is not used in this function.
Alice Wangef999242023-05-22 11:14:59 +000054 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 )
Alice Wang6ef44bc2023-02-08 12:08:32 +000069}
Alice Wang4d611772023-02-13 09:45:21 +000070
Alice Wangf59662d2023-02-10 16:07:56 +000071/// 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.
74pub 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();
Alice Wangef999242023-05-22 11:14:59 +000077 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +010078 // 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.
Alice Wangef999242023-05-22 11:14:59 +000081 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 )?;
Alice Wangf59662d2023-02-10 16:07:56 +000091 Ok((public_key, private_key))
92}
93
Alice Wangfd9ebcf2023-10-12 15:07:47 +000094/// 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`.
98pub fn derive_cdi_leaf_priv(dice_artifacts: &dyn DiceArtifacts) -> Result<PrivateKey> {
99 let cdi_priv_key_seed = derive_cdi_private_key_seed(dice_artifacts.cdi_attest())?;
100 let (_, private_key) = keypair_from_seed(cdi_priv_key_seed.as_array())?;
101 Ok(private_key)
102}
103
Alice Wang8722d9e2023-02-13 14:56:56 +0000104/// Signs the `message` with the give `private_key` using `DiceSign`.
105pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature> {
106 let mut signature = [0u8; SIGNATURE_SIZE];
Alice Wangef999242023-05-22 11:14:59 +0000107 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +0100108 // SAFETY: The function writes to the `signature` within the given bounds, and only reads
109 // the message and the private key. The first argument context is not used in this function.
Alice Wangef999242023-05-22 11:14:59 +0000110 unsafe {
111 DiceSign(
112 ptr::null_mut(), // context
113 message.as_ptr(),
114 message.len(),
115 private_key.as_ptr(),
116 signature.as_mut_ptr(),
117 )
118 },
119 signature.len(),
120 )?;
Alice Wang8722d9e2023-02-13 14:56:56 +0000121 Ok(signature)
122}
123
124/// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
125pub fn verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()> {
Alice Wangef999242023-05-22 11:14:59 +0000126 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +0100127 // SAFETY: only reads the messages, signature and public key as constant values.
128 // The first argument context is not used in this function.
Alice Wangef999242023-05-22 11:14:59 +0000129 unsafe {
130 DiceVerify(
131 ptr::null_mut(), // context
132 message.as_ptr(),
133 message.len(),
134 signature.as_ptr(),
135 public_key.as_ptr(),
136 )
137 },
138 0,
139 )
Alice Wang8722d9e2023-02-13 14:56:56 +0000140}
141
Alice Wang4d611772023-02-13 09:45:21 +0000142/// Generates an X.509 certificate from the given `subject_private_key_seed` and
143/// `input_values`, and signed by `authority_private_key_seed`.
144/// The subject private key seed is supplied here so the implementation can choose
145/// between asymmetric mechanisms, for example ECDSA vs Ed25519.
146/// Returns the actual size of the generated certificate.
147pub fn generate_certificate(
148 subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
149 authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
150 input_values: &InputValues,
151 certificate: &mut [u8],
152) -> Result<usize> {
153 let mut certificate_actual_size = 0;
Alice Wangef999242023-05-22 11:14:59 +0000154 check_result(
Andrew Walbran7f30e542023-07-07 13:42:25 +0100155 // SAFETY: The function writes to the `certificate` within the given bounds, and only reads
156 // the input values and the key seeds. The first argument context is not used in this
157 // function.
Alice Wangef999242023-05-22 11:14:59 +0000158 unsafe {
159 DiceGenerateCertificate(
160 ptr::null_mut(), // context
161 subject_private_key_seed.as_ptr(),
162 authority_private_key_seed.as_ptr(),
163 input_values.as_ptr(),
164 certificate.len(),
165 certificate.as_mut_ptr(),
166 &mut certificate_actual_size,
167 )
168 },
169 certificate_actual_size,
170 )?;
Alice Wang4d611772023-02-13 09:45:21 +0000171 Ok(certificate_actual_size)
172}