Merge "Added keystore2_unsafe_fuzzer"
This commit is contained in:
commit
65f8bf69c5
4 changed files with 278 additions and 28 deletions
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
|
18
keystore2/src/fuzzers/README.md
Normal file
18
keystore2/src/fuzzers/README.md
Normal file
|
@ -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
|
||||
```
|
248
keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
Normal file
248
keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
Normal file
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue