1*e1997b9aSAndroid Build Coastguard Worker // Copyright 2020, 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 //! This module implements safe wrappers for some crypto operations required by
16*e1997b9aSAndroid Build Coastguard Worker //! Keystore 2.0.
17*e1997b9aSAndroid Build Coastguard Worker
18*e1997b9aSAndroid Build Coastguard Worker mod error;
19*e1997b9aSAndroid Build Coastguard Worker pub mod zvec;
20*e1997b9aSAndroid Build Coastguard Worker pub use error::Error;
21*e1997b9aSAndroid Build Coastguard Worker use keystore2_crypto_bindgen::{
22*e1997b9aSAndroid Build Coastguard Worker extractSubjectFromCertificate, hmacSha256, randomBytes, AES_gcm_decrypt, AES_gcm_encrypt,
23*e1997b9aSAndroid Build Coastguard Worker ECDHComputeKey, ECKEYGenerateKey, ECKEYMarshalPrivateKey, ECKEYParsePrivateKey,
24*e1997b9aSAndroid Build Coastguard Worker ECPOINTOct2Point, ECPOINTPoint2Oct, EC_KEY_free, EC_KEY_get0_public_key, EC_POINT_free,
25*e1997b9aSAndroid Build Coastguard Worker HKDFExpand, HKDFExtract, EC_KEY, EC_MAX_BYTES, EC_POINT, EVP_MAX_MD_SIZE, PBKDF2,
26*e1997b9aSAndroid Build Coastguard Worker };
27*e1997b9aSAndroid Build Coastguard Worker use std::convert::TryFrom;
28*e1997b9aSAndroid Build Coastguard Worker use std::convert::TryInto;
29*e1997b9aSAndroid Build Coastguard Worker use std::marker::PhantomData;
30*e1997b9aSAndroid Build Coastguard Worker pub use zvec::ZVec;
31*e1997b9aSAndroid Build Coastguard Worker
32*e1997b9aSAndroid Build Coastguard Worker /// Length of the expected initialization vector.
33*e1997b9aSAndroid Build Coastguard Worker pub const GCM_IV_LENGTH: usize = 12;
34*e1997b9aSAndroid Build Coastguard Worker /// Length of the expected AEAD TAG.
35*e1997b9aSAndroid Build Coastguard Worker pub const TAG_LENGTH: usize = 16;
36*e1997b9aSAndroid Build Coastguard Worker /// Length of an AES 256 key in bytes.
37*e1997b9aSAndroid Build Coastguard Worker pub const AES_256_KEY_LENGTH: usize = 32;
38*e1997b9aSAndroid Build Coastguard Worker /// Length of an AES 128 key in bytes.
39*e1997b9aSAndroid Build Coastguard Worker pub const AES_128_KEY_LENGTH: usize = 16;
40*e1997b9aSAndroid Build Coastguard Worker /// Length of the expected salt for key from password generation.
41*e1997b9aSAndroid Build Coastguard Worker pub const SALT_LENGTH: usize = 16;
42*e1997b9aSAndroid Build Coastguard Worker /// Length of an HMAC-SHA256 tag in bytes.
43*e1997b9aSAndroid Build Coastguard Worker pub const HMAC_SHA256_LEN: usize = 32;
44*e1997b9aSAndroid Build Coastguard Worker
45*e1997b9aSAndroid Build Coastguard Worker /// Older versions of keystore produced IVs with four extra
46*e1997b9aSAndroid Build Coastguard Worker /// ignored zero bytes at the end; recognise and trim those.
47*e1997b9aSAndroid Build Coastguard Worker pub const LEGACY_IV_LENGTH: usize = 16;
48*e1997b9aSAndroid Build Coastguard Worker
49*e1997b9aSAndroid Build Coastguard Worker /// Generate an AES256 key, essentially 32 random bytes from the underlying
50*e1997b9aSAndroid Build Coastguard Worker /// boringssl library discretely stuffed into a ZVec.
generate_aes256_key() -> Result<ZVec, Error>51*e1997b9aSAndroid Build Coastguard Worker pub fn generate_aes256_key() -> Result<ZVec, Error> {
52*e1997b9aSAndroid Build Coastguard Worker let mut key = ZVec::new(AES_256_KEY_LENGTH)?;
53*e1997b9aSAndroid Build Coastguard Worker // Safety: key has the same length as the requested number of random bytes.
54*e1997b9aSAndroid Build Coastguard Worker if unsafe { randomBytes(key.as_mut_ptr(), AES_256_KEY_LENGTH) } {
55*e1997b9aSAndroid Build Coastguard Worker Ok(key)
56*e1997b9aSAndroid Build Coastguard Worker } else {
57*e1997b9aSAndroid Build Coastguard Worker Err(Error::RandomNumberGenerationFailed)
58*e1997b9aSAndroid Build Coastguard Worker }
59*e1997b9aSAndroid Build Coastguard Worker }
60*e1997b9aSAndroid Build Coastguard Worker
61*e1997b9aSAndroid Build Coastguard Worker /// Generate a salt.
generate_salt() -> Result<Vec<u8>, Error>62*e1997b9aSAndroid Build Coastguard Worker pub fn generate_salt() -> Result<Vec<u8>, Error> {
63*e1997b9aSAndroid Build Coastguard Worker generate_random_data(SALT_LENGTH)
64*e1997b9aSAndroid Build Coastguard Worker }
65*e1997b9aSAndroid Build Coastguard Worker
66*e1997b9aSAndroid Build Coastguard Worker /// Generate random data of the given size.
generate_random_data(size: usize) -> Result<Vec<u8>, Error>67*e1997b9aSAndroid Build Coastguard Worker pub fn generate_random_data(size: usize) -> Result<Vec<u8>, Error> {
68*e1997b9aSAndroid Build Coastguard Worker let mut data = vec![0; size];
69*e1997b9aSAndroid Build Coastguard Worker // Safety: data has the same length as the requested number of random bytes.
70*e1997b9aSAndroid Build Coastguard Worker if unsafe { randomBytes(data.as_mut_ptr(), size) } {
71*e1997b9aSAndroid Build Coastguard Worker Ok(data)
72*e1997b9aSAndroid Build Coastguard Worker } else {
73*e1997b9aSAndroid Build Coastguard Worker Err(Error::RandomNumberGenerationFailed)
74*e1997b9aSAndroid Build Coastguard Worker }
75*e1997b9aSAndroid Build Coastguard Worker }
76*e1997b9aSAndroid Build Coastguard Worker
77*e1997b9aSAndroid Build Coastguard Worker /// Perform HMAC-SHA256.
hmac_sha256(key: &[u8], msg: &[u8]) -> Result<Vec<u8>, Error>78*e1997b9aSAndroid Build Coastguard Worker pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> Result<Vec<u8>, Error> {
79*e1997b9aSAndroid Build Coastguard Worker let mut tag = vec![0; HMAC_SHA256_LEN];
80*e1997b9aSAndroid Build Coastguard Worker // Safety: The first two pairs of arguments must point to const buffers with
81*e1997b9aSAndroid Build Coastguard Worker // size given by the second arg of the pair. The final pair of arguments
82*e1997b9aSAndroid Build Coastguard Worker // must point to an output buffer with size given by the second arg of the
83*e1997b9aSAndroid Build Coastguard Worker // pair.
84*e1997b9aSAndroid Build Coastguard Worker match unsafe {
85*e1997b9aSAndroid Build Coastguard Worker hmacSha256(key.as_ptr(), key.len(), msg.as_ptr(), msg.len(), tag.as_mut_ptr(), tag.len())
86*e1997b9aSAndroid Build Coastguard Worker } {
87*e1997b9aSAndroid Build Coastguard Worker true => Ok(tag),
88*e1997b9aSAndroid Build Coastguard Worker false => Err(Error::HmacSha256Failed),
89*e1997b9aSAndroid Build Coastguard Worker }
90*e1997b9aSAndroid Build Coastguard Worker }
91*e1997b9aSAndroid Build Coastguard Worker
92*e1997b9aSAndroid Build Coastguard Worker /// Uses AES GCM to decipher a message given an initialization vector, aead tag, and key.
93*e1997b9aSAndroid Build Coastguard Worker /// This function accepts 128 and 256-bit keys and uses AES128 and AES256 respectively based
94*e1997b9aSAndroid Build Coastguard Worker /// on the key length.
95*e1997b9aSAndroid Build Coastguard Worker /// This function returns the plaintext message in a ZVec because it is assumed that
96*e1997b9aSAndroid Build Coastguard Worker /// it contains sensitive information that should be zeroed from memory before its buffer is
97*e1997b9aSAndroid Build Coastguard Worker /// freed. Input key is taken as a slice for flexibility, but it is recommended that it is held
98*e1997b9aSAndroid Build Coastguard Worker /// in a ZVec as well.
aes_gcm_decrypt(data: &[u8], iv: &[u8], tag: &[u8], key: &[u8]) -> Result<ZVec, Error>99*e1997b9aSAndroid Build Coastguard Worker pub fn aes_gcm_decrypt(data: &[u8], iv: &[u8], tag: &[u8], key: &[u8]) -> Result<ZVec, Error> {
100*e1997b9aSAndroid Build Coastguard Worker // Old versions of aes_gcm_encrypt produced 16 byte IVs, but the last four bytes were ignored
101*e1997b9aSAndroid Build Coastguard Worker // so trim these to the correct size.
102*e1997b9aSAndroid Build Coastguard Worker let iv = match iv.len() {
103*e1997b9aSAndroid Build Coastguard Worker GCM_IV_LENGTH => iv,
104*e1997b9aSAndroid Build Coastguard Worker LEGACY_IV_LENGTH => &iv[..GCM_IV_LENGTH],
105*e1997b9aSAndroid Build Coastguard Worker _ => return Err(Error::InvalidIvLength),
106*e1997b9aSAndroid Build Coastguard Worker };
107*e1997b9aSAndroid Build Coastguard Worker if tag.len() != TAG_LENGTH {
108*e1997b9aSAndroid Build Coastguard Worker return Err(Error::InvalidAeadTagLength);
109*e1997b9aSAndroid Build Coastguard Worker }
110*e1997b9aSAndroid Build Coastguard Worker
111*e1997b9aSAndroid Build Coastguard Worker match key.len() {
112*e1997b9aSAndroid Build Coastguard Worker AES_128_KEY_LENGTH | AES_256_KEY_LENGTH => {}
113*e1997b9aSAndroid Build Coastguard Worker _ => return Err(Error::InvalidKeyLength),
114*e1997b9aSAndroid Build Coastguard Worker }
115*e1997b9aSAndroid Build Coastguard Worker
116*e1997b9aSAndroid Build Coastguard Worker let mut result = ZVec::new(data.len())?;
117*e1997b9aSAndroid Build Coastguard Worker
118*e1997b9aSAndroid Build Coastguard Worker // Safety: The first two arguments must point to buffers with a size given by the third
119*e1997b9aSAndroid Build Coastguard Worker // argument. We pass the length of the key buffer along with the key.
120*e1997b9aSAndroid Build Coastguard Worker // The `iv` buffer must be 12 bytes and the `tag` buffer 16, which we check above.
121*e1997b9aSAndroid Build Coastguard Worker match unsafe {
122*e1997b9aSAndroid Build Coastguard Worker AES_gcm_decrypt(
123*e1997b9aSAndroid Build Coastguard Worker data.as_ptr(),
124*e1997b9aSAndroid Build Coastguard Worker result.as_mut_ptr(),
125*e1997b9aSAndroid Build Coastguard Worker data.len(),
126*e1997b9aSAndroid Build Coastguard Worker key.as_ptr(),
127*e1997b9aSAndroid Build Coastguard Worker key.len(),
128*e1997b9aSAndroid Build Coastguard Worker iv.as_ptr(),
129*e1997b9aSAndroid Build Coastguard Worker tag.as_ptr(),
130*e1997b9aSAndroid Build Coastguard Worker )
131*e1997b9aSAndroid Build Coastguard Worker } {
132*e1997b9aSAndroid Build Coastguard Worker true => Ok(result),
133*e1997b9aSAndroid Build Coastguard Worker false => Err(Error::DecryptionFailed),
134*e1997b9aSAndroid Build Coastguard Worker }
135*e1997b9aSAndroid Build Coastguard Worker }
136*e1997b9aSAndroid Build Coastguard Worker
137*e1997b9aSAndroid Build Coastguard Worker /// Uses AES GCM to encrypt a message given a key.
138*e1997b9aSAndroid Build Coastguard Worker /// This function accepts 128 and 256-bit keys and uses AES128 and AES256 respectively based on
139*e1997b9aSAndroid Build Coastguard Worker /// the key length. The function generates an initialization vector. The return value is a tuple
140*e1997b9aSAndroid Build Coastguard Worker /// of `(ciphertext, iv, tag)`.
aes_gcm_encrypt(plaintext: &[u8], key: &[u8]) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), Error>141*e1997b9aSAndroid Build Coastguard Worker pub fn aes_gcm_encrypt(plaintext: &[u8], key: &[u8]) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), Error> {
142*e1997b9aSAndroid Build Coastguard Worker let mut iv = vec![0; GCM_IV_LENGTH];
143*e1997b9aSAndroid Build Coastguard Worker // Safety: iv is GCM_IV_LENGTH bytes long.
144*e1997b9aSAndroid Build Coastguard Worker if !unsafe { randomBytes(iv.as_mut_ptr(), GCM_IV_LENGTH) } {
145*e1997b9aSAndroid Build Coastguard Worker return Err(Error::RandomNumberGenerationFailed);
146*e1997b9aSAndroid Build Coastguard Worker }
147*e1997b9aSAndroid Build Coastguard Worker
148*e1997b9aSAndroid Build Coastguard Worker match key.len() {
149*e1997b9aSAndroid Build Coastguard Worker AES_128_KEY_LENGTH | AES_256_KEY_LENGTH => {}
150*e1997b9aSAndroid Build Coastguard Worker _ => return Err(Error::InvalidKeyLength),
151*e1997b9aSAndroid Build Coastguard Worker }
152*e1997b9aSAndroid Build Coastguard Worker
153*e1997b9aSAndroid Build Coastguard Worker let mut ciphertext: Vec<u8> = vec![0; plaintext.len()];
154*e1997b9aSAndroid Build Coastguard Worker let mut tag: Vec<u8> = vec![0; TAG_LENGTH];
155*e1997b9aSAndroid Build Coastguard Worker // Safety: The first two arguments must point to buffers with a size given by the third
156*e1997b9aSAndroid Build Coastguard Worker // argument. We pass the length of the key buffer along with the key.
157*e1997b9aSAndroid Build Coastguard Worker // The `iv` buffer must be 12 bytes and the `tag` buffer 16, which we check above.
158*e1997b9aSAndroid Build Coastguard Worker if unsafe {
159*e1997b9aSAndroid Build Coastguard Worker AES_gcm_encrypt(
160*e1997b9aSAndroid Build Coastguard Worker plaintext.as_ptr(),
161*e1997b9aSAndroid Build Coastguard Worker ciphertext.as_mut_ptr(),
162*e1997b9aSAndroid Build Coastguard Worker plaintext.len(),
163*e1997b9aSAndroid Build Coastguard Worker key.as_ptr(),
164*e1997b9aSAndroid Build Coastguard Worker key.len(),
165*e1997b9aSAndroid Build Coastguard Worker iv.as_ptr(),
166*e1997b9aSAndroid Build Coastguard Worker tag.as_mut_ptr(),
167*e1997b9aSAndroid Build Coastguard Worker )
168*e1997b9aSAndroid Build Coastguard Worker } {
169*e1997b9aSAndroid Build Coastguard Worker Ok((ciphertext, iv, tag))
170*e1997b9aSAndroid Build Coastguard Worker } else {
171*e1997b9aSAndroid Build Coastguard Worker Err(Error::EncryptionFailed)
172*e1997b9aSAndroid Build Coastguard Worker }
173*e1997b9aSAndroid Build Coastguard Worker }
174*e1997b9aSAndroid Build Coastguard Worker
175*e1997b9aSAndroid Build Coastguard Worker /// A high-entropy synthetic password from which an AES key may be derived.
176*e1997b9aSAndroid Build Coastguard Worker pub enum Password<'a> {
177*e1997b9aSAndroid Build Coastguard Worker /// Borrow an existing byte array
178*e1997b9aSAndroid Build Coastguard Worker Ref(&'a [u8]),
179*e1997b9aSAndroid Build Coastguard Worker /// Use an owned ZVec to store the key
180*e1997b9aSAndroid Build Coastguard Worker Owned(ZVec),
181*e1997b9aSAndroid Build Coastguard Worker }
182*e1997b9aSAndroid Build Coastguard Worker
183*e1997b9aSAndroid Build Coastguard Worker impl<'a> From<&'a [u8]> for Password<'a> {
from(pw: &'a [u8]) -> Self184*e1997b9aSAndroid Build Coastguard Worker fn from(pw: &'a [u8]) -> Self {
185*e1997b9aSAndroid Build Coastguard Worker Self::Ref(pw)
186*e1997b9aSAndroid Build Coastguard Worker }
187*e1997b9aSAndroid Build Coastguard Worker }
188*e1997b9aSAndroid Build Coastguard Worker
189*e1997b9aSAndroid Build Coastguard Worker impl<'a> Password<'a> {
get_key(&'a self) -> &'a [u8]190*e1997b9aSAndroid Build Coastguard Worker fn get_key(&'a self) -> &'a [u8] {
191*e1997b9aSAndroid Build Coastguard Worker match self {
192*e1997b9aSAndroid Build Coastguard Worker Self::Ref(b) => b,
193*e1997b9aSAndroid Build Coastguard Worker Self::Owned(z) => z,
194*e1997b9aSAndroid Build Coastguard Worker }
195*e1997b9aSAndroid Build Coastguard Worker }
196*e1997b9aSAndroid Build Coastguard Worker
197*e1997b9aSAndroid Build Coastguard Worker /// Derives a key from the given password and salt, using PBKDF2 with 8192 iterations.
198*e1997b9aSAndroid Build Coastguard Worker ///
199*e1997b9aSAndroid Build Coastguard Worker /// The salt length must be 16 bytes, and the output key length must be 16 or 32 bytes.
200*e1997b9aSAndroid Build Coastguard Worker ///
201*e1997b9aSAndroid Build Coastguard Worker /// This function exists only for backwards compatibility reasons. Keystore now receives only
202*e1997b9aSAndroid Build Coastguard Worker /// high-entropy synthetic passwords, which do not require key stretching.
derive_key_pbkdf2(&self, salt: &[u8], out_len: usize) -> Result<ZVec, Error>203*e1997b9aSAndroid Build Coastguard Worker pub fn derive_key_pbkdf2(&self, salt: &[u8], out_len: usize) -> Result<ZVec, Error> {
204*e1997b9aSAndroid Build Coastguard Worker if salt.len() != SALT_LENGTH {
205*e1997b9aSAndroid Build Coastguard Worker return Err(Error::InvalidSaltLength);
206*e1997b9aSAndroid Build Coastguard Worker }
207*e1997b9aSAndroid Build Coastguard Worker match out_len {
208*e1997b9aSAndroid Build Coastguard Worker AES_128_KEY_LENGTH | AES_256_KEY_LENGTH => {}
209*e1997b9aSAndroid Build Coastguard Worker _ => return Err(Error::InvalidKeyLength),
210*e1997b9aSAndroid Build Coastguard Worker }
211*e1997b9aSAndroid Build Coastguard Worker
212*e1997b9aSAndroid Build Coastguard Worker let pw = self.get_key();
213*e1997b9aSAndroid Build Coastguard Worker let mut result = ZVec::new(out_len)?;
214*e1997b9aSAndroid Build Coastguard Worker
215*e1997b9aSAndroid Build Coastguard Worker // Safety: We checked that the salt is exactly 16 bytes long. The other pointers are valid,
216*e1997b9aSAndroid Build Coastguard Worker // and have matching lengths.
217*e1997b9aSAndroid Build Coastguard Worker unsafe {
218*e1997b9aSAndroid Build Coastguard Worker PBKDF2(
219*e1997b9aSAndroid Build Coastguard Worker result.as_mut_ptr(),
220*e1997b9aSAndroid Build Coastguard Worker result.len(),
221*e1997b9aSAndroid Build Coastguard Worker pw.as_ptr() as *const std::os::raw::c_char,
222*e1997b9aSAndroid Build Coastguard Worker pw.len(),
223*e1997b9aSAndroid Build Coastguard Worker salt.as_ptr(),
224*e1997b9aSAndroid Build Coastguard Worker )
225*e1997b9aSAndroid Build Coastguard Worker };
226*e1997b9aSAndroid Build Coastguard Worker
227*e1997b9aSAndroid Build Coastguard Worker Ok(result)
228*e1997b9aSAndroid Build Coastguard Worker }
229*e1997b9aSAndroid Build Coastguard Worker
230*e1997b9aSAndroid Build Coastguard Worker /// Derives a key from the given high-entropy synthetic password and salt, using HKDF.
derive_key_hkdf(&self, salt: &[u8], out_len: usize) -> Result<ZVec, Error>231*e1997b9aSAndroid Build Coastguard Worker pub fn derive_key_hkdf(&self, salt: &[u8], out_len: usize) -> Result<ZVec, Error> {
232*e1997b9aSAndroid Build Coastguard Worker let prk = hkdf_extract(self.get_key(), salt)?;
233*e1997b9aSAndroid Build Coastguard Worker let info = [];
234*e1997b9aSAndroid Build Coastguard Worker hkdf_expand(out_len, &prk, &info)
235*e1997b9aSAndroid Build Coastguard Worker }
236*e1997b9aSAndroid Build Coastguard Worker
237*e1997b9aSAndroid Build Coastguard Worker /// Try to make another Password object with the same data.
try_clone(&self) -> Result<Password<'static>, Error>238*e1997b9aSAndroid Build Coastguard Worker pub fn try_clone(&self) -> Result<Password<'static>, Error> {
239*e1997b9aSAndroid Build Coastguard Worker Ok(Password::Owned(ZVec::try_from(self.get_key())?))
240*e1997b9aSAndroid Build Coastguard Worker }
241*e1997b9aSAndroid Build Coastguard Worker }
242*e1997b9aSAndroid Build Coastguard Worker
243*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl HKDF_extract function.
hkdf_extract(secret: &[u8], salt: &[u8]) -> Result<ZVec, Error>244*e1997b9aSAndroid Build Coastguard Worker pub fn hkdf_extract(secret: &[u8], salt: &[u8]) -> Result<ZVec, Error> {
245*e1997b9aSAndroid Build Coastguard Worker let max_size: usize = EVP_MAX_MD_SIZE.try_into().unwrap();
246*e1997b9aSAndroid Build Coastguard Worker let mut buf = ZVec::new(max_size)?;
247*e1997b9aSAndroid Build Coastguard Worker let mut out_len = 0;
248*e1997b9aSAndroid Build Coastguard Worker // Safety: HKDF_extract writes at most EVP_MAX_MD_SIZE bytes.
249*e1997b9aSAndroid Build Coastguard Worker // Secret and salt point to valid buffers.
250*e1997b9aSAndroid Build Coastguard Worker let result = unsafe {
251*e1997b9aSAndroid Build Coastguard Worker HKDFExtract(
252*e1997b9aSAndroid Build Coastguard Worker buf.as_mut_ptr(),
253*e1997b9aSAndroid Build Coastguard Worker &mut out_len,
254*e1997b9aSAndroid Build Coastguard Worker secret.as_ptr(),
255*e1997b9aSAndroid Build Coastguard Worker secret.len(),
256*e1997b9aSAndroid Build Coastguard Worker salt.as_ptr(),
257*e1997b9aSAndroid Build Coastguard Worker salt.len(),
258*e1997b9aSAndroid Build Coastguard Worker )
259*e1997b9aSAndroid Build Coastguard Worker };
260*e1997b9aSAndroid Build Coastguard Worker if !result {
261*e1997b9aSAndroid Build Coastguard Worker return Err(Error::HKDFExtractFailed);
262*e1997b9aSAndroid Build Coastguard Worker }
263*e1997b9aSAndroid Build Coastguard Worker // According to the boringssl API, this should never happen.
264*e1997b9aSAndroid Build Coastguard Worker if out_len > max_size {
265*e1997b9aSAndroid Build Coastguard Worker return Err(Error::HKDFExtractFailed);
266*e1997b9aSAndroid Build Coastguard Worker }
267*e1997b9aSAndroid Build Coastguard Worker // HKDF_extract may write fewer than the maximum number of bytes, so we
268*e1997b9aSAndroid Build Coastguard Worker // truncate the buffer.
269*e1997b9aSAndroid Build Coastguard Worker buf.reduce_len(out_len);
270*e1997b9aSAndroid Build Coastguard Worker Ok(buf)
271*e1997b9aSAndroid Build Coastguard Worker }
272*e1997b9aSAndroid Build Coastguard Worker
273*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl HKDF_expand function.
hkdf_expand(out_len: usize, prk: &[u8], info: &[u8]) -> Result<ZVec, Error>274*e1997b9aSAndroid Build Coastguard Worker pub fn hkdf_expand(out_len: usize, prk: &[u8], info: &[u8]) -> Result<ZVec, Error> {
275*e1997b9aSAndroid Build Coastguard Worker let mut buf = ZVec::new(out_len)?;
276*e1997b9aSAndroid Build Coastguard Worker // Safety: HKDF_expand writes out_len bytes to the buffer.
277*e1997b9aSAndroid Build Coastguard Worker // prk and info are valid buffers.
278*e1997b9aSAndroid Build Coastguard Worker let result = unsafe {
279*e1997b9aSAndroid Build Coastguard Worker HKDFExpand(buf.as_mut_ptr(), out_len, prk.as_ptr(), prk.len(), info.as_ptr(), info.len())
280*e1997b9aSAndroid Build Coastguard Worker };
281*e1997b9aSAndroid Build Coastguard Worker if !result {
282*e1997b9aSAndroid Build Coastguard Worker return Err(Error::HKDFExpandFailed);
283*e1997b9aSAndroid Build Coastguard Worker }
284*e1997b9aSAndroid Build Coastguard Worker Ok(buf)
285*e1997b9aSAndroid Build Coastguard Worker }
286*e1997b9aSAndroid Build Coastguard Worker
287*e1997b9aSAndroid Build Coastguard Worker /// A wrapper around the boringssl EC_KEY type that frees it on drop.
288*e1997b9aSAndroid Build Coastguard Worker pub struct ECKey(*mut EC_KEY);
289*e1997b9aSAndroid Build Coastguard Worker
290*e1997b9aSAndroid Build Coastguard Worker impl Drop for ECKey {
drop(&mut self)291*e1997b9aSAndroid Build Coastguard Worker fn drop(&mut self) {
292*e1997b9aSAndroid Build Coastguard Worker // Safety: We only create ECKey objects for valid EC_KEYs
293*e1997b9aSAndroid Build Coastguard Worker // and they are the sole owners of those keys.
294*e1997b9aSAndroid Build Coastguard Worker unsafe { EC_KEY_free(self.0) };
295*e1997b9aSAndroid Build Coastguard Worker }
296*e1997b9aSAndroid Build Coastguard Worker }
297*e1997b9aSAndroid Build Coastguard Worker
298*e1997b9aSAndroid Build Coastguard Worker // Wrappers around the boringssl EC_POINT type.
299*e1997b9aSAndroid Build Coastguard Worker // The EC_POINT can either be owned (and therefore mutable) or a pointer to an
300*e1997b9aSAndroid Build Coastguard Worker // EC_POINT owned by someone else (and thus immutable). The former are freed
301*e1997b9aSAndroid Build Coastguard Worker // on drop.
302*e1997b9aSAndroid Build Coastguard Worker
303*e1997b9aSAndroid Build Coastguard Worker /// An owned EC_POINT object.
304*e1997b9aSAndroid Build Coastguard Worker pub struct OwnedECPoint(*mut EC_POINT);
305*e1997b9aSAndroid Build Coastguard Worker
306*e1997b9aSAndroid Build Coastguard Worker /// A pointer to an EC_POINT object.
307*e1997b9aSAndroid Build Coastguard Worker pub struct BorrowedECPoint<'a> {
308*e1997b9aSAndroid Build Coastguard Worker data: *const EC_POINT,
309*e1997b9aSAndroid Build Coastguard Worker phantom: PhantomData<&'a EC_POINT>,
310*e1997b9aSAndroid Build Coastguard Worker }
311*e1997b9aSAndroid Build Coastguard Worker
312*e1997b9aSAndroid Build Coastguard Worker impl OwnedECPoint {
313*e1997b9aSAndroid Build Coastguard Worker /// Get the wrapped EC_POINT object.
get_point(&self) -> &EC_POINT314*e1997b9aSAndroid Build Coastguard Worker pub fn get_point(&self) -> &EC_POINT {
315*e1997b9aSAndroid Build Coastguard Worker // Safety: We only create OwnedECPoint objects for valid EC_POINTs.
316*e1997b9aSAndroid Build Coastguard Worker unsafe { self.0.as_ref().unwrap() }
317*e1997b9aSAndroid Build Coastguard Worker }
318*e1997b9aSAndroid Build Coastguard Worker }
319*e1997b9aSAndroid Build Coastguard Worker
320*e1997b9aSAndroid Build Coastguard Worker impl<'a> BorrowedECPoint<'a> {
321*e1997b9aSAndroid Build Coastguard Worker /// Get the wrapped EC_POINT object.
get_point(&self) -> &EC_POINT322*e1997b9aSAndroid Build Coastguard Worker pub fn get_point(&self) -> &EC_POINT {
323*e1997b9aSAndroid Build Coastguard Worker // Safety: We only create BorrowedECPoint objects for valid EC_POINTs.
324*e1997b9aSAndroid Build Coastguard Worker unsafe { self.data.as_ref().unwrap() }
325*e1997b9aSAndroid Build Coastguard Worker }
326*e1997b9aSAndroid Build Coastguard Worker }
327*e1997b9aSAndroid Build Coastguard Worker
328*e1997b9aSAndroid Build Coastguard Worker impl Drop for OwnedECPoint {
drop(&mut self)329*e1997b9aSAndroid Build Coastguard Worker fn drop(&mut self) {
330*e1997b9aSAndroid Build Coastguard Worker // Safety: We only create OwnedECPoint objects for valid
331*e1997b9aSAndroid Build Coastguard Worker // EC_POINTs and they are the sole owners of those points.
332*e1997b9aSAndroid Build Coastguard Worker unsafe { EC_POINT_free(self.0) };
333*e1997b9aSAndroid Build Coastguard Worker }
334*e1997b9aSAndroid Build Coastguard Worker }
335*e1997b9aSAndroid Build Coastguard Worker
336*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl ECDH_compute_key function.
ecdh_compute_key(pub_key: &EC_POINT, priv_key: &ECKey) -> Result<ZVec, Error>337*e1997b9aSAndroid Build Coastguard Worker pub fn ecdh_compute_key(pub_key: &EC_POINT, priv_key: &ECKey) -> Result<ZVec, Error> {
338*e1997b9aSAndroid Build Coastguard Worker let mut buf = ZVec::new(EC_MAX_BYTES)?;
339*e1997b9aSAndroid Build Coastguard Worker let result =
340*e1997b9aSAndroid Build Coastguard Worker // Safety: Our ECDHComputeKey wrapper passes EC_MAX_BYES to ECDH_compute_key, which
341*e1997b9aSAndroid Build Coastguard Worker // writes at most that many bytes to the output.
342*e1997b9aSAndroid Build Coastguard Worker // The two keys are valid objects.
343*e1997b9aSAndroid Build Coastguard Worker unsafe { ECDHComputeKey(buf.as_mut_ptr() as *mut std::ffi::c_void, pub_key, priv_key.0) };
344*e1997b9aSAndroid Build Coastguard Worker if result == -1 {
345*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ECDHComputeKeyFailed);
346*e1997b9aSAndroid Build Coastguard Worker }
347*e1997b9aSAndroid Build Coastguard Worker let out_len = result.try_into().unwrap();
348*e1997b9aSAndroid Build Coastguard Worker // According to the boringssl API, this should never happen.
349*e1997b9aSAndroid Build Coastguard Worker if out_len > buf.len() {
350*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ECDHComputeKeyFailed);
351*e1997b9aSAndroid Build Coastguard Worker }
352*e1997b9aSAndroid Build Coastguard Worker // ECDH_compute_key may write fewer than the maximum number of bytes, so we
353*e1997b9aSAndroid Build Coastguard Worker // truncate the buffer.
354*e1997b9aSAndroid Build Coastguard Worker buf.reduce_len(out_len);
355*e1997b9aSAndroid Build Coastguard Worker Ok(buf)
356*e1997b9aSAndroid Build Coastguard Worker }
357*e1997b9aSAndroid Build Coastguard Worker
358*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl EC_KEY_generate_key function.
ec_key_generate_key() -> Result<ECKey, Error>359*e1997b9aSAndroid Build Coastguard Worker pub fn ec_key_generate_key() -> Result<ECKey, Error> {
360*e1997b9aSAndroid Build Coastguard Worker // Safety: Creates a new key on its own.
361*e1997b9aSAndroid Build Coastguard Worker let key = unsafe { ECKEYGenerateKey() };
362*e1997b9aSAndroid Build Coastguard Worker if key.is_null() {
363*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ECKEYGenerateKeyFailed);
364*e1997b9aSAndroid Build Coastguard Worker }
365*e1997b9aSAndroid Build Coastguard Worker Ok(ECKey(key))
366*e1997b9aSAndroid Build Coastguard Worker }
367*e1997b9aSAndroid Build Coastguard Worker
368*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl EC_KEY_marshal_private_key function.
ec_key_marshal_private_key(key: &ECKey) -> Result<ZVec, Error>369*e1997b9aSAndroid Build Coastguard Worker pub fn ec_key_marshal_private_key(key: &ECKey) -> Result<ZVec, Error> {
370*e1997b9aSAndroid Build Coastguard Worker let len = 73; // Empirically observed length of private key
371*e1997b9aSAndroid Build Coastguard Worker let mut buf = ZVec::new(len)?;
372*e1997b9aSAndroid Build Coastguard Worker // Safety: the key is valid.
373*e1997b9aSAndroid Build Coastguard Worker // This will not write past the specified length of the buffer; if the
374*e1997b9aSAndroid Build Coastguard Worker // len above is too short, it returns 0.
375*e1997b9aSAndroid Build Coastguard Worker let written_len = unsafe { ECKEYMarshalPrivateKey(key.0, buf.as_mut_ptr(), buf.len()) };
376*e1997b9aSAndroid Build Coastguard Worker if written_len == len {
377*e1997b9aSAndroid Build Coastguard Worker Ok(buf)
378*e1997b9aSAndroid Build Coastguard Worker } else {
379*e1997b9aSAndroid Build Coastguard Worker Err(Error::ECKEYMarshalPrivateKeyFailed)
380*e1997b9aSAndroid Build Coastguard Worker }
381*e1997b9aSAndroid Build Coastguard Worker }
382*e1997b9aSAndroid Build Coastguard Worker
383*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl EC_KEY_parse_private_key function.
ec_key_parse_private_key(buf: &[u8]) -> Result<ECKey, Error>384*e1997b9aSAndroid Build Coastguard Worker pub fn ec_key_parse_private_key(buf: &[u8]) -> Result<ECKey, Error> {
385*e1997b9aSAndroid Build Coastguard Worker // Safety: this will not read past the specified length of the buffer.
386*e1997b9aSAndroid Build Coastguard Worker // It fails if less than the whole buffer is consumed.
387*e1997b9aSAndroid Build Coastguard Worker let key = unsafe { ECKEYParsePrivateKey(buf.as_ptr(), buf.len()) };
388*e1997b9aSAndroid Build Coastguard Worker if key.is_null() {
389*e1997b9aSAndroid Build Coastguard Worker Err(Error::ECKEYParsePrivateKeyFailed)
390*e1997b9aSAndroid Build Coastguard Worker } else {
391*e1997b9aSAndroid Build Coastguard Worker Ok(ECKey(key))
392*e1997b9aSAndroid Build Coastguard Worker }
393*e1997b9aSAndroid Build Coastguard Worker }
394*e1997b9aSAndroid Build Coastguard Worker
395*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl EC_KEY_get0_public_key function.
ec_key_get0_public_key(key: &ECKey) -> BorrowedECPoint396*e1997b9aSAndroid Build Coastguard Worker pub fn ec_key_get0_public_key(key: &ECKey) -> BorrowedECPoint {
397*e1997b9aSAndroid Build Coastguard Worker // Safety: The key is valid.
398*e1997b9aSAndroid Build Coastguard Worker // This returns a pointer to a key, so we create an immutable variant.
399*e1997b9aSAndroid Build Coastguard Worker BorrowedECPoint { data: unsafe { EC_KEY_get0_public_key(key.0) }, phantom: PhantomData }
400*e1997b9aSAndroid Build Coastguard Worker }
401*e1997b9aSAndroid Build Coastguard Worker
402*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl EC_POINT_point2oct.
ec_point_point_to_oct(point: &EC_POINT) -> Result<Vec<u8>, Error>403*e1997b9aSAndroid Build Coastguard Worker pub fn ec_point_point_to_oct(point: &EC_POINT) -> Result<Vec<u8>, Error> {
404*e1997b9aSAndroid Build Coastguard Worker // We fix the length to 133 (1 + 2 * field_elem_size), as we get an error if it's too small.
405*e1997b9aSAndroid Build Coastguard Worker let len = 133;
406*e1997b9aSAndroid Build Coastguard Worker let mut buf = vec![0; len];
407*e1997b9aSAndroid Build Coastguard Worker // Safety: EC_POINT_point2oct writes at most len bytes. The point is valid.
408*e1997b9aSAndroid Build Coastguard Worker let result = unsafe { ECPOINTPoint2Oct(point, buf.as_mut_ptr(), len) };
409*e1997b9aSAndroid Build Coastguard Worker if result == 0 {
410*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ECPoint2OctFailed);
411*e1997b9aSAndroid Build Coastguard Worker }
412*e1997b9aSAndroid Build Coastguard Worker // According to the boringssl API, this should never happen.
413*e1997b9aSAndroid Build Coastguard Worker if result > len {
414*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ECPoint2OctFailed);
415*e1997b9aSAndroid Build Coastguard Worker }
416*e1997b9aSAndroid Build Coastguard Worker buf.resize(result, 0);
417*e1997b9aSAndroid Build Coastguard Worker Ok(buf)
418*e1997b9aSAndroid Build Coastguard Worker }
419*e1997b9aSAndroid Build Coastguard Worker
420*e1997b9aSAndroid Build Coastguard Worker /// Calls the boringssl EC_POINT_oct2point function.
ec_point_oct_to_point(buf: &[u8]) -> Result<OwnedECPoint, Error>421*e1997b9aSAndroid Build Coastguard Worker pub fn ec_point_oct_to_point(buf: &[u8]) -> Result<OwnedECPoint, Error> {
422*e1997b9aSAndroid Build Coastguard Worker // Safety: The buffer is valid.
423*e1997b9aSAndroid Build Coastguard Worker let result = unsafe { ECPOINTOct2Point(buf.as_ptr(), buf.len()) };
424*e1997b9aSAndroid Build Coastguard Worker if result.is_null() {
425*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ECPoint2OctFailed);
426*e1997b9aSAndroid Build Coastguard Worker }
427*e1997b9aSAndroid Build Coastguard Worker // Our C wrapper creates a new EC_POINT, so we mark this mutable and free
428*e1997b9aSAndroid Build Coastguard Worker // it on drop.
429*e1997b9aSAndroid Build Coastguard Worker Ok(OwnedECPoint(result))
430*e1997b9aSAndroid Build Coastguard Worker }
431*e1997b9aSAndroid Build Coastguard Worker
432*e1997b9aSAndroid Build Coastguard Worker /// Uses BoringSSL to extract the DER-encoded subject from a DER-encoded X.509 certificate.
parse_subject_from_certificate(cert_buf: &[u8]) -> Result<Vec<u8>, Error>433*e1997b9aSAndroid Build Coastguard Worker pub fn parse_subject_from_certificate(cert_buf: &[u8]) -> Result<Vec<u8>, Error> {
434*e1997b9aSAndroid Build Coastguard Worker // Try with a 200-byte output buffer, should be enough in all but bizarre cases.
435*e1997b9aSAndroid Build Coastguard Worker let mut retval = vec![0; 200];
436*e1997b9aSAndroid Build Coastguard Worker
437*e1997b9aSAndroid Build Coastguard Worker // Safety: extractSubjectFromCertificate reads at most cert_buf.len() bytes from cert_buf and
438*e1997b9aSAndroid Build Coastguard Worker // writes at most retval.len() bytes to retval.
439*e1997b9aSAndroid Build Coastguard Worker let mut size = unsafe {
440*e1997b9aSAndroid Build Coastguard Worker extractSubjectFromCertificate(
441*e1997b9aSAndroid Build Coastguard Worker cert_buf.as_ptr(),
442*e1997b9aSAndroid Build Coastguard Worker cert_buf.len(),
443*e1997b9aSAndroid Build Coastguard Worker retval.as_mut_ptr(),
444*e1997b9aSAndroid Build Coastguard Worker retval.len(),
445*e1997b9aSAndroid Build Coastguard Worker )
446*e1997b9aSAndroid Build Coastguard Worker };
447*e1997b9aSAndroid Build Coastguard Worker
448*e1997b9aSAndroid Build Coastguard Worker if size == 0 {
449*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ExtractSubjectFailed);
450*e1997b9aSAndroid Build Coastguard Worker }
451*e1997b9aSAndroid Build Coastguard Worker
452*e1997b9aSAndroid Build Coastguard Worker if size < 0 {
453*e1997b9aSAndroid Build Coastguard Worker // Our buffer wasn't big enough. Make one that is just the right size and try again.
454*e1997b9aSAndroid Build Coastguard Worker let negated_size = usize::try_from(-size).map_err(|_e| Error::ExtractSubjectFailed)?;
455*e1997b9aSAndroid Build Coastguard Worker retval = vec![0; negated_size];
456*e1997b9aSAndroid Build Coastguard Worker
457*e1997b9aSAndroid Build Coastguard Worker // Safety: extractSubjectFromCertificate reads at most cert_buf.len() bytes from cert_buf
458*e1997b9aSAndroid Build Coastguard Worker // and writes at most retval.len() bytes to retval.
459*e1997b9aSAndroid Build Coastguard Worker size = unsafe {
460*e1997b9aSAndroid Build Coastguard Worker extractSubjectFromCertificate(
461*e1997b9aSAndroid Build Coastguard Worker cert_buf.as_ptr(),
462*e1997b9aSAndroid Build Coastguard Worker cert_buf.len(),
463*e1997b9aSAndroid Build Coastguard Worker retval.as_mut_ptr(),
464*e1997b9aSAndroid Build Coastguard Worker retval.len(),
465*e1997b9aSAndroid Build Coastguard Worker )
466*e1997b9aSAndroid Build Coastguard Worker };
467*e1997b9aSAndroid Build Coastguard Worker
468*e1997b9aSAndroid Build Coastguard Worker if size <= 0 {
469*e1997b9aSAndroid Build Coastguard Worker return Err(Error::ExtractSubjectFailed);
470*e1997b9aSAndroid Build Coastguard Worker }
471*e1997b9aSAndroid Build Coastguard Worker }
472*e1997b9aSAndroid Build Coastguard Worker
473*e1997b9aSAndroid Build Coastguard Worker // Reduce buffer size to the amount written.
474*e1997b9aSAndroid Build Coastguard Worker let safe_size = usize::try_from(size).map_err(|_e| Error::ExtractSubjectFailed)?;
475*e1997b9aSAndroid Build Coastguard Worker retval.truncate(safe_size);
476*e1997b9aSAndroid Build Coastguard Worker
477*e1997b9aSAndroid Build Coastguard Worker Ok(retval)
478*e1997b9aSAndroid Build Coastguard Worker }
479*e1997b9aSAndroid Build Coastguard Worker
480*e1997b9aSAndroid Build Coastguard Worker #[cfg(test)]
481*e1997b9aSAndroid Build Coastguard Worker mod tests {
482*e1997b9aSAndroid Build Coastguard Worker
483*e1997b9aSAndroid Build Coastguard Worker use super::*;
484*e1997b9aSAndroid Build Coastguard Worker use keystore2_crypto_bindgen::{AES_gcm_decrypt, AES_gcm_encrypt, CreateKeyId, PBKDF2};
485*e1997b9aSAndroid Build Coastguard Worker
486*e1997b9aSAndroid Build Coastguard Worker #[test]
test_wrapper_roundtrip()487*e1997b9aSAndroid Build Coastguard Worker fn test_wrapper_roundtrip() {
488*e1997b9aSAndroid Build Coastguard Worker let key = generate_aes256_key().unwrap();
489*e1997b9aSAndroid Build Coastguard Worker let message = b"totally awesome message";
490*e1997b9aSAndroid Build Coastguard Worker let (cipher_text, iv, tag) = aes_gcm_encrypt(message, &key).unwrap();
491*e1997b9aSAndroid Build Coastguard Worker let message2 = aes_gcm_decrypt(&cipher_text, &iv, &tag, &key).unwrap();
492*e1997b9aSAndroid Build Coastguard Worker assert_eq!(message[..], message2[..])
493*e1997b9aSAndroid Build Coastguard Worker }
494*e1997b9aSAndroid Build Coastguard Worker
495*e1997b9aSAndroid Build Coastguard Worker #[test]
test_encrypt_decrypt()496*e1997b9aSAndroid Build Coastguard Worker fn test_encrypt_decrypt() {
497*e1997b9aSAndroid Build Coastguard Worker let input = vec![0; 16];
498*e1997b9aSAndroid Build Coastguard Worker let mut out = vec![0; 16];
499*e1997b9aSAndroid Build Coastguard Worker let mut out2 = vec![0; 16];
500*e1997b9aSAndroid Build Coastguard Worker let key = [0; 16];
501*e1997b9aSAndroid Build Coastguard Worker let iv = [0; 12];
502*e1997b9aSAndroid Build Coastguard Worker let mut tag = vec![0; 16];
503*e1997b9aSAndroid Build Coastguard Worker // SAFETY: The various pointers are obtained from references so they are valid, and
504*e1997b9aSAndroid Build Coastguard Worker // `AES_gcm_encrypt` and `AES_gcm_decrypt` don't do anything with them after they return.
505*e1997b9aSAndroid Build Coastguard Worker unsafe {
506*e1997b9aSAndroid Build Coastguard Worker let res = AES_gcm_encrypt(
507*e1997b9aSAndroid Build Coastguard Worker input.as_ptr(),
508*e1997b9aSAndroid Build Coastguard Worker out.as_mut_ptr(),
509*e1997b9aSAndroid Build Coastguard Worker 16,
510*e1997b9aSAndroid Build Coastguard Worker key.as_ptr(),
511*e1997b9aSAndroid Build Coastguard Worker 16,
512*e1997b9aSAndroid Build Coastguard Worker iv.as_ptr(),
513*e1997b9aSAndroid Build Coastguard Worker tag.as_mut_ptr(),
514*e1997b9aSAndroid Build Coastguard Worker );
515*e1997b9aSAndroid Build Coastguard Worker assert!(res);
516*e1997b9aSAndroid Build Coastguard Worker assert_ne!(out, input);
517*e1997b9aSAndroid Build Coastguard Worker assert_ne!(tag, input);
518*e1997b9aSAndroid Build Coastguard Worker let res = AES_gcm_decrypt(
519*e1997b9aSAndroid Build Coastguard Worker out.as_ptr(),
520*e1997b9aSAndroid Build Coastguard Worker out2.as_mut_ptr(),
521*e1997b9aSAndroid Build Coastguard Worker 16,
522*e1997b9aSAndroid Build Coastguard Worker key.as_ptr(),
523*e1997b9aSAndroid Build Coastguard Worker 16,
524*e1997b9aSAndroid Build Coastguard Worker iv.as_ptr(),
525*e1997b9aSAndroid Build Coastguard Worker tag.as_ptr(),
526*e1997b9aSAndroid Build Coastguard Worker );
527*e1997b9aSAndroid Build Coastguard Worker assert!(res);
528*e1997b9aSAndroid Build Coastguard Worker assert_eq!(out2, input);
529*e1997b9aSAndroid Build Coastguard Worker }
530*e1997b9aSAndroid Build Coastguard Worker }
531*e1997b9aSAndroid Build Coastguard Worker
532*e1997b9aSAndroid Build Coastguard Worker #[test]
test_create_key_id()533*e1997b9aSAndroid Build Coastguard Worker fn test_create_key_id() {
534*e1997b9aSAndroid Build Coastguard Worker let blob = [0; 16];
535*e1997b9aSAndroid Build Coastguard Worker let mut out: u64 = 0;
536*e1997b9aSAndroid Build Coastguard Worker // SAFETY: The pointers are obtained from references so they are valid, the length matches
537*e1997b9aSAndroid Build Coastguard Worker // the length of the array, and `CreateKeyId` doesn't access them after it returns.
538*e1997b9aSAndroid Build Coastguard Worker unsafe {
539*e1997b9aSAndroid Build Coastguard Worker let res = CreateKeyId(blob.as_ptr(), blob.len(), &mut out);
540*e1997b9aSAndroid Build Coastguard Worker assert!(res);
541*e1997b9aSAndroid Build Coastguard Worker assert_ne!(out, 0);
542*e1997b9aSAndroid Build Coastguard Worker }
543*e1997b9aSAndroid Build Coastguard Worker }
544*e1997b9aSAndroid Build Coastguard Worker
545*e1997b9aSAndroid Build Coastguard Worker #[test]
test_pbkdf2()546*e1997b9aSAndroid Build Coastguard Worker fn test_pbkdf2() {
547*e1997b9aSAndroid Build Coastguard Worker let mut key = vec![0; 16];
548*e1997b9aSAndroid Build Coastguard Worker let pw = [0; 16];
549*e1997b9aSAndroid Build Coastguard Worker let salt = [0; 16];
550*e1997b9aSAndroid Build Coastguard Worker // SAFETY: The pointers are obtained from references so they are valid, the salt is the
551*e1997b9aSAndroid Build Coastguard Worker // expected length, the other lengths match the lengths of the arrays, and `PBKDF2` doesn't
552*e1997b9aSAndroid Build Coastguard Worker // access them after it returns.
553*e1997b9aSAndroid Build Coastguard Worker unsafe {
554*e1997b9aSAndroid Build Coastguard Worker PBKDF2(key.as_mut_ptr(), key.len(), pw.as_ptr(), pw.len(), salt.as_ptr());
555*e1997b9aSAndroid Build Coastguard Worker }
556*e1997b9aSAndroid Build Coastguard Worker assert_ne!(key, vec![0; 16]);
557*e1997b9aSAndroid Build Coastguard Worker }
558*e1997b9aSAndroid Build Coastguard Worker
559*e1997b9aSAndroid Build Coastguard Worker #[test]
test_hkdf()560*e1997b9aSAndroid Build Coastguard Worker fn test_hkdf() {
561*e1997b9aSAndroid Build Coastguard Worker let result = hkdf_extract(&[0; 16], &[0; 16]);
562*e1997b9aSAndroid Build Coastguard Worker assert!(result.is_ok());
563*e1997b9aSAndroid Build Coastguard Worker for out_len in 4..=8 {
564*e1997b9aSAndroid Build Coastguard Worker let result = hkdf_expand(out_len, &[0; 16], &[0; 16]);
565*e1997b9aSAndroid Build Coastguard Worker assert!(result.is_ok());
566*e1997b9aSAndroid Build Coastguard Worker assert_eq!(result.unwrap().len(), out_len);
567*e1997b9aSAndroid Build Coastguard Worker }
568*e1997b9aSAndroid Build Coastguard Worker }
569*e1997b9aSAndroid Build Coastguard Worker
570*e1997b9aSAndroid Build Coastguard Worker #[test]
test_ec() -> Result<(), Error>571*e1997b9aSAndroid Build Coastguard Worker fn test_ec() -> Result<(), Error> {
572*e1997b9aSAndroid Build Coastguard Worker let priv0 = ec_key_generate_key()?;
573*e1997b9aSAndroid Build Coastguard Worker assert!(!priv0.0.is_null());
574*e1997b9aSAndroid Build Coastguard Worker let pub0 = ec_key_get0_public_key(&priv0);
575*e1997b9aSAndroid Build Coastguard Worker
576*e1997b9aSAndroid Build Coastguard Worker let priv1 = ec_key_generate_key()?;
577*e1997b9aSAndroid Build Coastguard Worker let pub1 = ec_key_get0_public_key(&priv1);
578*e1997b9aSAndroid Build Coastguard Worker
579*e1997b9aSAndroid Build Coastguard Worker let priv0s = ec_key_marshal_private_key(&priv0)?;
580*e1997b9aSAndroid Build Coastguard Worker let pub0s = ec_point_point_to_oct(pub0.get_point())?;
581*e1997b9aSAndroid Build Coastguard Worker let pub1s = ec_point_point_to_oct(pub1.get_point())?;
582*e1997b9aSAndroid Build Coastguard Worker
583*e1997b9aSAndroid Build Coastguard Worker let priv0 = ec_key_parse_private_key(&priv0s)?;
584*e1997b9aSAndroid Build Coastguard Worker let pub0 = ec_point_oct_to_point(&pub0s)?;
585*e1997b9aSAndroid Build Coastguard Worker let pub1 = ec_point_oct_to_point(&pub1s)?;
586*e1997b9aSAndroid Build Coastguard Worker
587*e1997b9aSAndroid Build Coastguard Worker let left_key = ecdh_compute_key(pub0.get_point(), &priv1)?;
588*e1997b9aSAndroid Build Coastguard Worker let right_key = ecdh_compute_key(pub1.get_point(), &priv0)?;
589*e1997b9aSAndroid Build Coastguard Worker
590*e1997b9aSAndroid Build Coastguard Worker assert_eq!(left_key, right_key);
591*e1997b9aSAndroid Build Coastguard Worker Ok(())
592*e1997b9aSAndroid Build Coastguard Worker }
593*e1997b9aSAndroid Build Coastguard Worker
594*e1997b9aSAndroid Build Coastguard Worker #[test]
test_hmac_sha256()595*e1997b9aSAndroid Build Coastguard Worker fn test_hmac_sha256() {
596*e1997b9aSAndroid Build Coastguard Worker let key = b"This is the key";
597*e1997b9aSAndroid Build Coastguard Worker let msg1 = b"This is a message";
598*e1997b9aSAndroid Build Coastguard Worker let msg2 = b"This is another message";
599*e1997b9aSAndroid Build Coastguard Worker let tag1a = hmac_sha256(key, msg1).unwrap();
600*e1997b9aSAndroid Build Coastguard Worker assert_eq!(tag1a.len(), HMAC_SHA256_LEN);
601*e1997b9aSAndroid Build Coastguard Worker let tag1b = hmac_sha256(key, msg1).unwrap();
602*e1997b9aSAndroid Build Coastguard Worker assert_eq!(tag1a, tag1b);
603*e1997b9aSAndroid Build Coastguard Worker let tag2 = hmac_sha256(key, msg2).unwrap();
604*e1997b9aSAndroid Build Coastguard Worker assert_eq!(tag2.len(), HMAC_SHA256_LEN);
605*e1997b9aSAndroid Build Coastguard Worker assert_ne!(tag1a, tag2);
606*e1997b9aSAndroid Build Coastguard Worker }
607*e1997b9aSAndroid Build Coastguard Worker }
608