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}; 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 { new(entropy: &Entropy) -> Result<Drbg>24 pub fn new(entropy: &Entropy) -> Result<Drbg> { 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. 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 reseed(&mut self, entropy: &Entropy) -> Result<()>33 pub fn reseed(&mut self, entropy: &Entropy) -> Result<()> { 34 ensure!( 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. 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 generate(&mut self, buf: &mut [u8]) -> Result<()>45 pub fn generate(&mut self, buf: &mut [u8]) -> Result<()> { 46 ensure!( 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. 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 { drop(&mut self)67 fn drop(&mut self) { 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. 70 unsafe { 71 bssl_sys::CTR_DRBG_free(self.0); 72 } 73 } 74 } 75 76 // SAFETY: CTR_DRBG functions can be called from any thread. 77 unsafe impl Send for Drbg {} 78