blob: 8222b266bf1cd3d51791b19b23943548a061c74b [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 Wangf59662d2023-02-10 16:07:56 +000020 Hash, InputValues, PrivateKey, PublicKey, Signature, HASH_SIZE, PRIVATE_KEY_SEED_SIZE,
21 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];
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}
Alice Wang6ef44bc2023-02-08 12:08:32 +000044
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`.
47pub 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}
Alice Wang4d611772023-02-13 09:45:21 +000064
Alice Wangf59662d2023-02-10 16:07:56 +000065/// 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.
68pub 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
Alice Wang8722d9e2023-02-13 14:56:56 +000084/// Signs the `message` with the give `private_key` using `DiceSign`.
85pub 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`.
102pub 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
Alice Wang4d611772023-02-13 09:45:21 +0000116/// 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.
121pub 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}