blob: 648fd91c082a7fc706b32f01ce48117658534cef [file] [log] [blame]
Alice Wang9c40eca2023-02-03 13:10:24 +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 implements a retry version for multiple DICE functions that
16//! require preallocated output buffer. As the retry functions require
17//! memory allocation on heap, currently we only expose these functions in
18//! std environment.
19
20use crate::bcc::bcc_format_config_descriptor;
21use crate::error::{DiceError, Result};
22use std::ffi::CStr;
23
24/// Retries the given function with bigger output buffer size.
25fn retry_with_bigger_buffer<F>(mut f: F) -> Result<Vec<u8>>
26where
27 F: FnMut(&mut Vec<u8>) -> Result<usize>,
28{
29 const INITIAL_BUFFER_SIZE: usize = 256;
30 const MAX_BUFFER_SIZE: usize = 64 * 1024 * 1024;
31
32 let mut buffer = vec![0u8; INITIAL_BUFFER_SIZE];
33 while buffer.len() <= MAX_BUFFER_SIZE {
34 match f(&mut buffer) {
35 Err(DiceError::BufferTooSmall) => {
36 let new_size = buffer.len() * 2;
37 buffer.resize(new_size, 0);
38 }
39 Err(e) => return Err(e),
40 Ok(actual_size) => {
41 if actual_size > buffer.len() {
42 panic!(
43 "actual_size larger than buffer size: open-dice function
44 may have written past the end of the buffer."
45 );
46 }
47 buffer.truncate(actual_size);
48 return Ok(buffer);
49 }
50 }
51 }
52 Err(DiceError::PlatformError)
53}
54
55/// Formats a configuration descriptor following the BCC's specification.
56pub fn retry_bcc_format_config_descriptor(
57 name: Option<&CStr>,
58 version: Option<u64>,
59 resettable: bool,
60) -> Result<Vec<u8>> {
61 retry_with_bigger_buffer(|buffer| {
62 bcc_format_config_descriptor(name, version, resettable, buffer)
63 })
64}