Paul Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 1 | // 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 | |
| 15 | use anyhow::{ensure, Result}; |
Paul Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 16 | |
| 17 | pub const ENTROPY_LEN: usize = bssl_sys::CTR_DRBG_ENTROPY_LEN as usize; |
| 18 | |
| 19 | pub type Entropy = [u8; ENTROPY_LEN]; |
| 20 | |
| 21 | pub struct Drbg(*mut bssl_sys::CTR_DRBG_STATE); |
| 22 | |
| 23 | impl Drbg { |
| 24 | pub fn new(entropy: &Entropy) -> Result<Drbg> { |
Andrew Walbran | c768733 | 2023-07-21 17:26:09 +0100 | [diff] [blame] | 25 | // 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 Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 28 | 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 Walbran | c768733 | 2023-07-21 17:26:09 +0100 | [diff] [blame] | 35 | // 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 Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 38 | 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 Walbran | c768733 | 2023-07-21 17:26:09 +0100 | [diff] [blame] | 47 | // 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 Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 51 | 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 | |
| 66 | impl Drop for Drbg { |
| 67 | fn drop(&mut self) { |
Andrew Walbran | c768733 | 2023-07-21 17:26:09 +0100 | [diff] [blame] | 68 | // 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 Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 70 | unsafe { |
| 71 | bssl_sys::CTR_DRBG_free(self.0); |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | |
Andrew Walbran | c768733 | 2023-07-21 17:26:09 +0100 | [diff] [blame] | 76 | // SAFETY: CTR_DRBG functions can be called from any thread. |
Paul Crowley | 9da969e | 2022-09-16 23:42:24 +0000 | [diff] [blame] | 77 | unsafe impl Send for Drbg {} |