1*e1997b9aSAndroid Build Coastguard Worker // Copyright (C) 2022 The Android Open Source Project 2*e1997b9aSAndroid Build Coastguard Worker // 3*e1997b9aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*e1997b9aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*e1997b9aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*e1997b9aSAndroid Build Coastguard Worker // 7*e1997b9aSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 8*e1997b9aSAndroid Build Coastguard Worker // 9*e1997b9aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*e1997b9aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*e1997b9aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e1997b9aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*e1997b9aSAndroid Build Coastguard Worker // limitations under the License. 14*e1997b9aSAndroid Build Coastguard Worker 15*e1997b9aSAndroid Build Coastguard Worker use anyhow::{ensure, Result}; 16*e1997b9aSAndroid Build Coastguard Worker 17*e1997b9aSAndroid Build Coastguard Worker pub const ENTROPY_LEN: usize = bssl_sys::CTR_DRBG_ENTROPY_LEN as usize; 18*e1997b9aSAndroid Build Coastguard Worker 19*e1997b9aSAndroid Build Coastguard Worker pub type Entropy = [u8; ENTROPY_LEN]; 20*e1997b9aSAndroid Build Coastguard Worker 21*e1997b9aSAndroid Build Coastguard Worker pub struct Drbg(*mut bssl_sys::CTR_DRBG_STATE); 22*e1997b9aSAndroid Build Coastguard Worker 23*e1997b9aSAndroid Build Coastguard Worker impl Drbg { new(entropy: &Entropy) -> Result<Drbg>24*e1997b9aSAndroid Build Coastguard Worker pub fn new(entropy: &Entropy) -> Result<Drbg> { 25*e1997b9aSAndroid Build Coastguard Worker // SAFETY: entropy must be a valid pointer because it comes from a reference, and a null 26*e1997b9aSAndroid Build Coastguard Worker // pointer is allowed for personalization. CTR_DRBG_new doesn't retain the entropy pointer 27*e1997b9aSAndroid Build Coastguard Worker // for use after it returns. 28*e1997b9aSAndroid Build Coastguard Worker let p = unsafe { bssl_sys::CTR_DRBG_new(entropy.as_ptr(), std::ptr::null(), 0) }; 29*e1997b9aSAndroid Build Coastguard Worker ensure!(!p.is_null(), "CTR_DRBG_new failed"); 30*e1997b9aSAndroid Build Coastguard Worker Ok(Drbg(p)) 31*e1997b9aSAndroid Build Coastguard Worker } 32*e1997b9aSAndroid Build Coastguard Worker reseed(&mut self, entropy: &Entropy) -> Result<()>33*e1997b9aSAndroid Build Coastguard Worker pub fn reseed(&mut self, entropy: &Entropy) -> Result<()> { 34*e1997b9aSAndroid Build Coastguard Worker ensure!( 35*e1997b9aSAndroid Build Coastguard Worker // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in 36*e1997b9aSAndroid Build Coastguard Worker // Drbg::new above. The entropy pointer must be valid because it comes from a reference, 37*e1997b9aSAndroid Build Coastguard Worker // and CTR_DRBG_reseed doesn't retain it after it returns. 38*e1997b9aSAndroid Build Coastguard Worker unsafe { bssl_sys::CTR_DRBG_reseed(self.0, entropy.as_ptr(), std::ptr::null(), 0) } 39*e1997b9aSAndroid Build Coastguard Worker == 1, 40*e1997b9aSAndroid Build Coastguard Worker "CTR_DRBG_reseed failed" 41*e1997b9aSAndroid Build Coastguard Worker ); 42*e1997b9aSAndroid Build Coastguard Worker Ok(()) 43*e1997b9aSAndroid Build Coastguard Worker } 44*e1997b9aSAndroid Build Coastguard Worker generate(&mut self, buf: &mut [u8]) -> Result<()>45*e1997b9aSAndroid Build Coastguard Worker pub fn generate(&mut self, buf: &mut [u8]) -> Result<()> { 46*e1997b9aSAndroid Build Coastguard Worker ensure!( 47*e1997b9aSAndroid Build Coastguard Worker // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in 48*e1997b9aSAndroid Build Coastguard Worker // Drbg::new above. The out pointer and length must be valid and unaliased because they 49*e1997b9aSAndroid Build Coastguard Worker // come from a mutable slice reference, and CTR_DRBG_generate doesn't retain them after 50*e1997b9aSAndroid Build Coastguard Worker // it returns. 51*e1997b9aSAndroid Build Coastguard Worker unsafe { 52*e1997b9aSAndroid Build Coastguard Worker bssl_sys::CTR_DRBG_generate( 53*e1997b9aSAndroid Build Coastguard Worker self.0, 54*e1997b9aSAndroid Build Coastguard Worker buf.as_mut_ptr(), 55*e1997b9aSAndroid Build Coastguard Worker buf.len(), 56*e1997b9aSAndroid Build Coastguard Worker std::ptr::null(), 57*e1997b9aSAndroid Build Coastguard Worker 0, 58*e1997b9aSAndroid Build Coastguard Worker ) 59*e1997b9aSAndroid Build Coastguard Worker } == 1, 60*e1997b9aSAndroid Build Coastguard Worker "CTR_DRBG_generate failed" 61*e1997b9aSAndroid Build Coastguard Worker ); 62*e1997b9aSAndroid Build Coastguard Worker Ok(()) 63*e1997b9aSAndroid Build Coastguard Worker } 64*e1997b9aSAndroid Build Coastguard Worker } 65*e1997b9aSAndroid Build Coastguard Worker 66*e1997b9aSAndroid Build Coastguard Worker impl Drop for Drbg { drop(&mut self)67*e1997b9aSAndroid Build Coastguard Worker fn drop(&mut self) { 68*e1997b9aSAndroid Build Coastguard Worker // SAFETY: We know that self.0 is valid because it was initialised from CTR_DRBG_new in 69*e1997b9aSAndroid Build Coastguard Worker // Drbg::new above, and this is the only place that frees it. 70*e1997b9aSAndroid Build Coastguard Worker unsafe { 71*e1997b9aSAndroid Build Coastguard Worker bssl_sys::CTR_DRBG_free(self.0); 72*e1997b9aSAndroid Build Coastguard Worker } 73*e1997b9aSAndroid Build Coastguard Worker } 74*e1997b9aSAndroid Build Coastguard Worker } 75*e1997b9aSAndroid Build Coastguard Worker 76*e1997b9aSAndroid Build Coastguard Worker // SAFETY: CTR_DRBG functions can be called from any thread. 77*e1997b9aSAndroid Build Coastguard Worker unsafe impl Send for Drbg {} 78