blob: 808ea18fd1106f51c12af2262e87b41c7b676bf1 [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};
16use bssl_ffi as bssl_sys;
17
18pub const ENTROPY_LEN: usize = bssl_sys::CTR_DRBG_ENTROPY_LEN as usize;
19
20pub type Entropy = [u8; ENTROPY_LEN];
21
22pub struct Drbg(*mut bssl_sys::CTR_DRBG_STATE);
23
24impl Drbg {
25 pub fn new(entropy: &Entropy) -> Result<Drbg> {
Andrew Walbranc7687332023-07-21 17:26:09 +010026 // SAFETY: entropy must be a valid pointer because it comes from a reference, and a null
27 // pointer is allowed for personalization. CTR_DRBG_new doesn't retain the entropy pointer
28 // for use after it returns.
Paul Crowley9da969e2022-09-16 23:42:24 +000029 let p = unsafe { bssl_sys::CTR_DRBG_new(entropy.as_ptr(), std::ptr::null(), 0) };
30 ensure!(!p.is_null(), "CTR_DRBG_new failed");
31 Ok(Drbg(p))
32 }
33
34 pub fn reseed(&mut self, entropy: &Entropy) -> Result<()> {
35 ensure!(
Andrew Walbranc7687332023-07-21 17:26:09 +010036 // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in
37 // Drbg::new above. The entropy pointer must be valid because it comes from a reference,
38 // and CTR_DRBG_reseed doesn't retain it after it returns.
Paul Crowley9da969e2022-09-16 23:42:24 +000039 unsafe { bssl_sys::CTR_DRBG_reseed(self.0, entropy.as_ptr(), std::ptr::null(), 0) }
40 == 1,
41 "CTR_DRBG_reseed failed"
42 );
43 Ok(())
44 }
45
46 pub fn generate(&mut self, buf: &mut [u8]) -> Result<()> {
47 ensure!(
Andrew Walbranc7687332023-07-21 17:26:09 +010048 // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in
49 // Drbg::new above. The out pointer and length must be valid and unaliased because they
50 // come from a mutable slice reference, and CTR_DRBG_generate doesn't retain them after
51 // it returns.
Paul Crowley9da969e2022-09-16 23:42:24 +000052 unsafe {
53 bssl_sys::CTR_DRBG_generate(
54 self.0,
55 buf.as_mut_ptr(),
56 buf.len(),
57 std::ptr::null(),
58 0,
59 )
60 } == 1,
61 "CTR_DRBG_generate failed"
62 );
63 Ok(())
64 }
65}
66
67impl Drop for Drbg {
68 fn drop(&mut self) {
Andrew Walbranc7687332023-07-21 17:26:09 +010069 // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in
70 // Drbg::new above, and this is the only place that frees it.
Paul Crowley9da969e2022-09-16 23:42:24 +000071 unsafe {
72 bssl_sys::CTR_DRBG_free(self.0);
73 }
74 }
75}
76
Andrew Walbranc7687332023-07-21 17:26:09 +010077// SAFETY: CTR_DRBG functions can be called from any thread.
Paul Crowley9da969e2022-09-16 23:42:24 +000078unsafe impl Send for Drbg {}