blob: 71903530e85703064b3ff7e1ae89f9979cf4cea6 [file] [log] [blame]
Paul Crowley9da969e2022-09-16 23:42:24 +00001// Copyright (C) 2022 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
15use anyhow::{ensure, Result};
Paul Crowley9da969e2022-09-16 23:42:24 +000016
17pub const ENTROPY_LEN: usize = bssl_sys::CTR_DRBG_ENTROPY_LEN as usize;
18
19pub type Entropy = [u8; ENTROPY_LEN];
20
21pub struct Drbg(*mut bssl_sys::CTR_DRBG_STATE);
22
23impl Drbg {
24 pub fn new(entropy: &Entropy) -> Result<Drbg> {
Andrew Walbranc7687332023-07-21 17:26:09 +010025 // SAFETY: entropy must be a valid pointer because it comes from a reference, and a null
26 // pointer is allowed for personalization. CTR_DRBG_new doesn't retain the entropy pointer
27 // for use after it returns.
Paul Crowley9da969e2022-09-16 23:42:24 +000028 let p = unsafe { bssl_sys::CTR_DRBG_new(entropy.as_ptr(), std::ptr::null(), 0) };
29 ensure!(!p.is_null(), "CTR_DRBG_new failed");
30 Ok(Drbg(p))
31 }
32
33 pub fn reseed(&mut self, entropy: &Entropy) -> Result<()> {
34 ensure!(
Andrew Walbranc7687332023-07-21 17:26:09 +010035 // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in
36 // Drbg::new above. The entropy pointer must be valid because it comes from a reference,
37 // and CTR_DRBG_reseed doesn't retain it after it returns.
Paul Crowley9da969e2022-09-16 23:42:24 +000038 unsafe { bssl_sys::CTR_DRBG_reseed(self.0, entropy.as_ptr(), std::ptr::null(), 0) }
39 == 1,
40 "CTR_DRBG_reseed failed"
41 );
42 Ok(())
43 }
44
45 pub fn generate(&mut self, buf: &mut [u8]) -> Result<()> {
46 ensure!(
Andrew Walbranc7687332023-07-21 17:26:09 +010047 // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in
48 // Drbg::new above. The out pointer and length must be valid and unaliased because they
49 // come from a mutable slice reference, and CTR_DRBG_generate doesn't retain them after
50 // it returns.
Paul Crowley9da969e2022-09-16 23:42:24 +000051 unsafe {
52 bssl_sys::CTR_DRBG_generate(
53 self.0,
54 buf.as_mut_ptr(),
55 buf.len(),
56 std::ptr::null(),
57 0,
58 )
59 } == 1,
60 "CTR_DRBG_generate failed"
61 );
62 Ok(())
63 }
64}
65
66impl Drop for Drbg {
67 fn drop(&mut self) {
Andrew Walbranc7687332023-07-21 17:26:09 +010068 // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in
69 // Drbg::new above, and this is the only place that frees it.
Paul Crowley9da969e2022-09-16 23:42:24 +000070 unsafe {
71 bssl_sys::CTR_DRBG_free(self.0);
72 }
73 }
74}
75
Andrew Walbranc7687332023-07-21 17:26:09 +010076// SAFETY: CTR_DRBG functions can be called from any thread.
Paul Crowley9da969e2022-09-16 23:42:24 +000077unsafe impl Send for Drbg {}