blob: 21b7d9ec6e5300f6f8cc82441a9d9ffaed338130 [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::{
20 Hash, InputValues, PublicKey, Signature, HASH_SIZE, PRIVATE_KEY_SEED_SIZE, PRIVATE_KEY_SIZE,
21 SIGNATURE_SIZE,
22};
Alice Wang24954b42023-02-06 10:03:45 +000023use crate::error::{check_result, Result};
Alice Wang8722d9e2023-02-13 14:56:56 +000024use open_dice_cbor_bindgen::{DiceGenerateCertificate, DiceHash, DiceKdf, DiceSign, DiceVerify};
Alice Wang24954b42023-02-06 10:03:45 +000025use std::ptr;
26
27/// Hashes the provided input using DICE's hash function `DiceHash`.
28pub fn hash(input: &[u8]) -> Result<Hash> {
29 let mut output: Hash = [0; HASH_SIZE];
30 // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output buffer.
31 // The first argument context is not used in this function.
32 check_result(unsafe {
33 DiceHash(
34 ptr::null_mut(), // context
35 input.as_ptr(),
36 input.len(),
37 output.as_mut_ptr(),
38 )
39 })?;
40 Ok(output)
41}
Alice Wang6ef44bc2023-02-08 12:08:32 +000042
43/// An implementation of HKDF-SHA512. Derives a key of `derived_key.len()` bytes from `ikm`, `salt`,
44/// and `info`. The derived key is written to the `derived_key`.
45pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
46 // SAFETY: The function writes to the `derived_key`, within the given bounds, and only reads the
47 // input values. The first argument context is not used in this function.
48 check_result(unsafe {
49 DiceKdf(
50 ptr::null_mut(), // context
51 derived_key.len(),
52 ikm.as_ptr(),
53 ikm.len(),
54 salt.as_ptr(),
55 salt.len(),
56 info.as_ptr(),
57 info.len(),
58 derived_key.as_mut_ptr(),
59 )
60 })
61}
Alice Wang4d611772023-02-13 09:45:21 +000062
Alice Wang8722d9e2023-02-13 14:56:56 +000063/// Signs the `message` with the give `private_key` using `DiceSign`.
64pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature> {
65 let mut signature = [0u8; SIGNATURE_SIZE];
66 // SAFETY: The function writes to the `signature` within the given bounds, and only reads the
67 // message and the private key. The first argument context is not used in this function.
68 check_result(unsafe {
69 DiceSign(
70 ptr::null_mut(), // context
71 message.as_ptr(),
72 message.len(),
73 private_key.as_ptr(),
74 signature.as_mut_ptr(),
75 )
76 })?;
77 Ok(signature)
78}
79
80/// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
81pub fn verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()> {
82 // SAFETY: only reads the messages, signature and public key as constant values.
83 // The first argument context is not used in this function.
84 check_result(unsafe {
85 DiceVerify(
86 ptr::null_mut(), // context
87 message.as_ptr(),
88 message.len(),
89 signature.as_ptr(),
90 public_key.as_ptr(),
91 )
92 })
93}
94
Alice Wang4d611772023-02-13 09:45:21 +000095/// Generates an X.509 certificate from the given `subject_private_key_seed` and
96/// `input_values`, and signed by `authority_private_key_seed`.
97/// The subject private key seed is supplied here so the implementation can choose
98/// between asymmetric mechanisms, for example ECDSA vs Ed25519.
99/// Returns the actual size of the generated certificate.
100pub fn generate_certificate(
101 subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
102 authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
103 input_values: &InputValues,
104 certificate: &mut [u8],
105) -> Result<usize> {
106 let mut certificate_actual_size = 0;
107 // SAFETY: The function writes to the `certificate` within the given bounds, and only reads the
108 // input values and the key seeds. The first argument context is not used in this function.
109 check_result(unsafe {
110 DiceGenerateCertificate(
111 ptr::null_mut(), // context
112 subject_private_key_seed.as_ptr(),
113 authority_private_key_seed.as_ptr(),
114 input_values.as_ptr(),
115 certificate.len(),
116 certificate.as_mut_ptr(),
117 &mut certificate_actual_size,
118 )
119 })?;
120 Ok(certificate_actual_size)
121}