diff options
author | Devendra Singhi <devendra.singhi@ittiam.com> | 2022-08-04 14:33:29 +0530 |
---|---|---|
committer | Devendra Singhi <devendra.singhi@ittiam.com> | 2022-08-04 14:33:29 +0530 |
commit | 31863b1ab50516460864a0bc4ed69a4a4e05c5e3 (patch) | |
tree | dc5971bc38a3783fd973c4ee8e09e2e7c3a7ebc2 /keystore2/src/fuzzers | |
parent | af43ae73f906e3d5ae1cfcfc5628ce34b09777e6 (diff) | |
download | security-31863b1ab50516460864a0bc4ed69a4a4e05c5e3.tar.gz |
Added keystore2_unsafe_fuzzer
Test: ./keystore2_unsafe_fuzzer
Bug: 240524901
Change-Id: Ibb6d2c649f982bc1b5fc8d4a259087e53bac79aa
Diffstat (limited to 'keystore2/src/fuzzers')
-rw-r--r-- | keystore2/src/fuzzers/Android.bp | 14 | ||||
-rw-r--r-- | keystore2/src/fuzzers/README.md | 18 | ||||
-rw-r--r-- | keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs | 248 | ||||
-rw-r--r-- | keystore2/src/fuzzers/legacy_blob_fuzzer.rs | 26 |
4 files changed, 278 insertions, 28 deletions
diff --git a/keystore2/src/fuzzers/Android.bp b/keystore2/src/fuzzers/Android.bp index 384ab77f..3adb9226 100644 --- a/keystore2/src/fuzzers/Android.bp +++ b/keystore2/src/fuzzers/Android.bp @@ -17,13 +17,23 @@ package { } rust_fuzz { - name: "legacy_blob_fuzzer", - srcs: ["legacy_blob_fuzzer.rs"], + name: "keystore2_unsafe_fuzzer", + srcs: ["keystore2_unsafe_fuzzer.rs"], rustlibs: [ "libkeystore2", + "libkeystore2_crypto_rust", + "libkeystore2_vintf_rust", + "libkeystore2_aaid-rust", + "libkeystore2_apc_compat-rust", + "libkeystore2_selinux", + "libarbitrary", ], fuzz_config: { fuzz_on_haiku_device: true, fuzz_on_haiku_host: false, + cc: [ + "android-media-fuzzing-reports@google.com", + ], + componentid: 155276, }, } diff --git a/keystore2/src/fuzzers/README.md b/keystore2/src/fuzzers/README.md new file mode 100644 index 00000000..a4ed095b --- /dev/null +++ b/keystore2/src/fuzzers/README.md @@ -0,0 +1,18 @@ +# Fuzzers for libkeystore2 +## Table of contents ++ [keystore2_unsafe_fuzzer](#Keystore2Unsafe) + +# <a name="Keystore2Unsafe"></a> Fuzzer for Keystore2Unsafe +All the parameters of Keystore2Unsafe are populated randomly from libfuzzer. You can find the possible values in the fuzzer's source code. + +#### Steps to run +1. Build the fuzzer +``` +$ m -j$(nproc) keystore2_unsafe_fuzzer +``` + +2. Run on device +``` +$ adb sync data +$ adb shell /data/fuzz/${TARGET_ARCH}/keystore2_unsafe_fuzzer/keystore2_unsafe_fuzzer +``` diff --git a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs new file mode 100644 index 00000000..4c2419aa --- /dev/null +++ b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs @@ -0,0 +1,248 @@ +// Copyright 2022, The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Fuzzes unsafe APIs of libkeystore2 module + +#![feature(slice_internals)] +#![no_main] +#[macro_use] +extern crate libfuzzer_sys; + +use core::slice::memchr; +use keystore2::{legacy_blob::LegacyBlobLoader, utils::ui_opts_2_compat}; +use keystore2_aaid::get_aaid; +use keystore2_apc_compat::ApcHal; +use keystore2_crypto::{ + aes_gcm_decrypt, aes_gcm_encrypt, ec_key_generate_key, ec_key_get0_public_key, + ec_key_marshal_private_key, ec_key_parse_private_key, ec_point_oct_to_point, + ec_point_point_to_oct, ecdh_compute_key, generate_random_data, hkdf_expand, hkdf_extract, + hmac_sha256, parse_subject_from_certificate, Password, ZVec, +}; +use keystore2_selinux::{check_access, getpidcon, setcon, Backend, Context, KeystoreKeyBackend}; +use keystore2_vintf::{get_aidl_instances, get_hidl_instances}; +use libfuzzer_sys::arbitrary::Arbitrary; +use std::{ffi::CString, sync::Arc}; + +// Avoid allocating too much memory and crashing the fuzzer. +const MAX_SIZE_MODIFIER: usize = 1024; + +/// CString does not contain any internal 0 bytes +fn get_valid_cstring_data(data: &[u8]) -> &[u8] { + match memchr::memchr(0, data) { + Some(idx) => &data[0..idx], + None => data, + } +} + +#[derive(Arbitrary, Debug)] +enum FuzzCommand<'a> { + DecodeAlias { + string: String, + }, + TryFrom { + vector_data: Vec<u8>, + }, + GenerateRandomData { + size: usize, + }, + HmacSha256 { + key_hmac: &'a [u8], + msg: &'a [u8], + }, + AesGcmDecrypt { + data: &'a [u8], + iv: &'a [u8], + tag: &'a [u8], + key_aes_decrypt: &'a [u8], + }, + AesGcmEecrypt { + plaintext: &'a [u8], + key_aes_encrypt: &'a [u8], + }, + Password { + pw: &'a [u8], + salt: &'a [u8], + key_length: usize, + }, + HkdfExtract { + hkdf_secret: &'a [u8], + hkdf_salt: &'a [u8], + }, + HkdfExpand { + out_len: usize, + hkdf_prk: &'a [u8], + hkdf_info: &'a [u8], + }, + PublicPrivateKey { + ec_priv_buf: &'a [u8], + ec_oct_buf: &'a [u8], + }, + ParseSubjectFromCertificate { + parse_buf: &'a [u8], + }, + GetHidlInstances { + hidl_package: &'a str, + major_version: usize, + minor_version: usize, + hidl_interface_name: &'a str, + }, + GetAidlInstances { + aidl_package: &'a str, + version: usize, + aidl_interface_name: &'a str, + }, + GetAaid { + aaid_uid: u32, + }, + Hal { + opt: i32, + prompt_text: &'a str, + locale: &'a str, + extra_data: &'a [u8], + }, + Context { + context: &'a str, + }, + Backend { + namespace: &'a str, + }, + GetPidCon { + pid: i32, + }, + CheckAccess { + source: &'a [u8], + target: &'a [u8], + tclass: &'a str, + perm: &'a str, + }, + SetCon { + set_target: &'a [u8], + }, +} + +fuzz_target!(|commands: Vec<FuzzCommand>| { + for command in commands { + match command { + FuzzCommand::DecodeAlias { string } => { + let _res = LegacyBlobLoader::decode_alias(&string); + } + FuzzCommand::TryFrom { vector_data } => { + let _res = ZVec::try_from(vector_data); + } + FuzzCommand::GenerateRandomData { size } => { + let _res = generate_random_data(size % MAX_SIZE_MODIFIER); + } + FuzzCommand::HmacSha256 { key_hmac, msg } => { + let _res = hmac_sha256(key_hmac, msg); + } + FuzzCommand::AesGcmDecrypt { data, iv, tag, key_aes_decrypt } => { + let _res = aes_gcm_decrypt(data, iv, tag, key_aes_decrypt); + } + FuzzCommand::AesGcmEecrypt { plaintext, key_aes_encrypt } => { + let _res = aes_gcm_encrypt(plaintext, key_aes_encrypt); + } + FuzzCommand::Password { pw, salt, key_length } => { + let _res = Password::from(pw).derive_key(salt, key_length % MAX_SIZE_MODIFIER); + } + FuzzCommand::HkdfExtract { hkdf_secret, hkdf_salt } => { + let _res = hkdf_extract(hkdf_secret, hkdf_salt); + } + FuzzCommand::HkdfExpand { out_len, hkdf_prk, hkdf_info } => { + let _res = hkdf_expand(out_len % MAX_SIZE_MODIFIER, hkdf_prk, hkdf_info); + } + FuzzCommand::PublicPrivateKey { ec_priv_buf, ec_oct_buf } => { + let check_private_key = { + let mut check_private_key = ec_key_parse_private_key(ec_priv_buf); + if check_private_key.is_err() { + check_private_key = ec_key_generate_key(); + }; + check_private_key + }; + let check_ecpoint = ec_point_oct_to_point(ec_oct_buf); + if check_private_key.is_ok() { + let private_key = check_private_key.unwrap(); + ec_key_get0_public_key(&private_key); + let _res = ec_key_marshal_private_key(&private_key); + + if check_ecpoint.is_ok() { + let public_key = check_ecpoint.unwrap(); + let _res = ec_point_point_to_oct(public_key.get_point()); + let _res = ecdh_compute_key(public_key.get_point(), &private_key); + } + } + } + FuzzCommand::ParseSubjectFromCertificate { parse_buf } => { + let _res = parse_subject_from_certificate(parse_buf); + } + FuzzCommand::GetHidlInstances { + hidl_package, + major_version, + minor_version, + hidl_interface_name, + } => { + get_hidl_instances(hidl_package, major_version, minor_version, hidl_interface_name); + } + FuzzCommand::GetAidlInstances { aidl_package, version, aidl_interface_name } => { + get_aidl_instances(aidl_package, version, aidl_interface_name); + } + FuzzCommand::GetAaid { aaid_uid } => { + let _res = get_aaid(aaid_uid); + } + FuzzCommand::Hal { opt, prompt_text, locale, extra_data } => { + let hal = ApcHal::try_get_service(); + if hal.is_some() { + let hal = Arc::new(hal.unwrap()); + let apc_compat_options = ui_opts_2_compat(opt); + let prompt_text = + std::str::from_utf8(get_valid_cstring_data(prompt_text.as_bytes())) + .unwrap(); + let locale = + std::str::from_utf8(get_valid_cstring_data(locale.as_bytes())).unwrap(); + let _res = hal.prompt_user_confirmation( + prompt_text, + extra_data, + locale, + apc_compat_options, + move |_, _, _| {}, + ); + } + } + FuzzCommand::Context { context } => { + let _res = Context::new(context); + } + FuzzCommand::Backend { namespace } => { + let backend = KeystoreKeyBackend::new(); + if let Ok(backend) = backend { + let _res = backend.lookup(namespace); + } + } + FuzzCommand::GetPidCon { pid } => { + let _res = getpidcon(pid); + } + FuzzCommand::CheckAccess { source, target, tclass, perm } => { + let source = get_valid_cstring_data(source); + let target = get_valid_cstring_data(target); + let _res = check_access( + &CString::new(source).unwrap(), + &CString::new(target).unwrap(), + tclass, + perm, + ); + } + FuzzCommand::SetCon { set_target } => { + let _res = setcon(&CString::new(get_valid_cstring_data(set_target)).unwrap()); + } + } + } +}); diff --git a/keystore2/src/fuzzers/legacy_blob_fuzzer.rs b/keystore2/src/fuzzers/legacy_blob_fuzzer.rs deleted file mode 100644 index 7e3e848c..00000000 --- a/keystore2/src/fuzzers/legacy_blob_fuzzer.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2021, The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![allow(missing_docs)] -#![no_main] -#[macro_use] -extern crate libfuzzer_sys; -use keystore2::legacy_blob::LegacyBlobLoader; - -fuzz_target!(|data: &[u8]| { - if !data.is_empty() { - let string = data.iter().filter_map(|c| std::char::from_u32(*c as u32)).collect::<String>(); - let _res = LegacyBlobLoader::decode_alias(&string); - } -}); |