diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 296a9b7cf..976583677 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -119,3 +119,94 @@ doc = false name = "fuzz_tbor_part_info" path = "fuzz_targets/ddi/tbor/fuzz_tbor_part_info.rs" test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_aes_encrypt_decrypt" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_aes_encrypt_decrypt.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_aes_generate_key" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_aes_generate_key.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_concat_kdf_derive" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_concat_kdf_derive.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_ecc_generate_key" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_ecc_generate_key.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_ecc_sign" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_ecc_sign.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_ecdh_derive" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_ecdh_derive.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_get_unwrapping_key" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_get_unwrapping_key.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_hash" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_hash.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_hkdf_derive" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_hkdf_derive.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_hmac_generate_key" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_hmac_generate_key.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_hmac" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_hmac.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_rsa_mod_exp" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_rsa_mod_exp.rs" +test = false + +[[bin]] +bench = false +doc = false +name = "fuzz_tbor_unwrap_key" +path = "fuzz_targets/ddi/tbor/fuzz_tbor_unwrap_key.rs" +test = false diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_aes_encrypt_decrypt.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_aes_encrypt_decrypt.rs new file mode 100644 index 000000000..0021150ca --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_aes_encrypt_decrypt.rs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::AES_IV_LEN; +use azihsm_ddi_tbor_types::AES_KEY_SIZE_256; +use azihsm_ddi_tbor_types::AES_MSG_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborAesEncryptDecryptReq; +use azihsm_ddi_tbor_types::TborAesGenerateKeyReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_msg(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = AES_MSG_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + op: u8, + #[arbitrary(with = bounded_msg)] + msg: Vec, + iv: [u8; AES_IV_LEN], +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Generate an AES key to obtain a valid masked_key. + let keygen_req = TborAesGenerateKeyReq { + session_id: session.session_id(), + scope: 0b001, // KeyScope::Session + key_size: AES_KEY_SIZE_256, + }; + let masked_key = match ctx.tbor(&keygen_req) { + Ok(resp) => resp.masked_key, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + let req = TborAesEncryptDecryptReq { + session_id: session.session_id(), + masked_key, + op: input.op, + msg: input.msg, + iv: input.iv, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_aes_generate_key.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_aes_generate_key.rs new file mode 100644 index 000000000..25e7b3911 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_aes_generate_key.rs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborAesGenerateKeyReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + key_size: u8, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborAesGenerateKeyReq { + session_id: session.session_id(), + scope: input.scope, + key_size: input.key_size, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_concat_kdf_derive.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_concat_kdf_derive.rs new file mode 100644 index 000000000..d5ad48b4d --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_concat_kdf_derive.rs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::CONCAT_INFO_MAX_LEN; +use azihsm_ddi_tbor_types::ECC_CURVE_P256; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborConcatKdfDeriveReq; +use azihsm_ddi_tbor_types::TborEccGenerateKeyReq; +use azihsm_ddi_tbor_types::TborEcdhDeriveReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_info(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let len = usize::arbitrary(u)? % (CONCAT_INFO_MAX_LEN + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + hash_algo: u8, + kdf_alg: u8, + key_type: u8, + key_length: u8, + #[arbitrary(with = bounded_info)] + info: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Generate an ECC key pair for the ECDH derive. + let keygen_req = TborEccGenerateKeyReq { + session_id: session.session_id(), + scope: 0b001, // KeyScope::Session + curve: ECC_CURVE_P256, + }; + let keygen_resp = match ctx.tbor(&keygen_req) { + Ok(resp) => resp, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + // Derive an ECDH shared secret using the key's own pub key as peer. + let ecdh_req = TborEcdhDeriveReq { + session_id: session.session_id(), + scope: 0b001, + masked_key: keygen_resp.masked_key, + peer_pub_key: keygen_resp.pub_key, + }; + let masked_secret = match ctx.tbor(&ecdh_req) { + Ok(resp) => resp.masked_secret, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + let req = TborConcatKdfDeriveReq { + session_id: session.session_id(), + scope: input.scope, + hash_algo: input.hash_algo, + kdf_alg: input.kdf_alg, + key_type: input.key_type, + key_length: input.key_length, + masked_secret, + info: input.info, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecc_generate_key.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecc_generate_key.rs new file mode 100644 index 000000000..1bea60f27 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecc_generate_key.rs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborEccGenerateKeyReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + curve: u8, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborEccGenerateKeyReq { + session_id: session.session_id(), + scope: input.scope, + curve: input.curve, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecc_sign.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecc_sign.rs new file mode 100644 index 000000000..5c67d2981 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecc_sign.rs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::ECC_CURVE_P256; +use azihsm_ddi_tbor_types::ECC_DIGEST_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborEccGenerateKeyReq; +use azihsm_ddi_tbor_types::TborEccSignReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_digest(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = ECC_DIGEST_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + #[arbitrary(with = bounded_digest)] + digest: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Generate an ECC key to obtain a valid masked_key. + let keygen_req = TborEccGenerateKeyReq { + session_id: session.session_id(), + scope: 0b001, // KeyScope::Session + curve: ECC_CURVE_P256, + }; + let masked_key = match ctx.tbor(&keygen_req) { + Ok(resp) => resp.masked_key, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + let req = TborEccSignReq { + session_id: session.session_id(), + masked_key, + digest: input.digest, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecdh_derive.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecdh_derive.rs new file mode 100644 index 000000000..58ff4f477 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_ecdh_derive.rs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::ECC_CURVE_P256; +use azihsm_ddi_tbor_types::ECDH_PEER_PUB_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborEccGenerateKeyReq; +use azihsm_ddi_tbor_types::TborEcdhDeriveReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_peer_pub(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = ECDH_PEER_PUB_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + #[arbitrary(with = bounded_peer_pub)] + peer_pub_key: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Generate an ECC key to obtain a valid masked_key. + let keygen_req = TborEccGenerateKeyReq { + session_id: session.session_id(), + scope: 0b001, // KeyScope::Session + curve: ECC_CURVE_P256, + }; + let masked_key = match ctx.tbor(&keygen_req) { + Ok(resp) => resp.masked_key, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + let req = TborEcdhDeriveReq { + session_id: session.session_id(), + scope: input.scope, + masked_key, + peer_pub_key: input.peer_pub_key, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_get_unwrapping_key.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_get_unwrapping_key.rs new file mode 100644 index 000000000..b34997ed7 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_get_unwrapping_key.rs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborGetUnwrappingKeyReq; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fuzz_target!(|_input: &[u8]| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborGetUnwrappingKeyReq { + session_id: session.session_id(), + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hash.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hash.rs new file mode 100644 index 000000000..d20aef12f --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hash.rs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::HASH_MSG_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborHashReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_msg(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = HASH_MSG_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + algo: u8, + #[arbitrary(with = bounded_msg)] + msg: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborHashReq { + session_id: session.session_id(), + algo: input.algo, + msg: input.msg, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hkdf_derive.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hkdf_derive.rs new file mode 100644 index 000000000..85b81f577 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hkdf_derive.rs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::ECC_CURVE_P256; +use azihsm_ddi_tbor_types::HKDF_INFO_MAX_LEN; +use azihsm_ddi_tbor_types::HKDF_SALT_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborEccGenerateKeyReq; +use azihsm_ddi_tbor_types::TborEcdhDeriveReq; +use azihsm_ddi_tbor_types::TborHkdfDeriveReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_salt(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let len = usize::arbitrary(u)? % (HKDF_SALT_MAX_LEN + 1); + Ok(u.bytes(len)?.to_vec()) +} + +fn bounded_info(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let len = usize::arbitrary(u)? % (HKDF_INFO_MAX_LEN + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + hash_algo: u8, + key_type: u8, + key_length: u8, + #[arbitrary(with = bounded_salt)] + salt: Vec, + #[arbitrary(with = bounded_info)] + info: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Generate an ECC key pair for the ECDH derive. + let keygen_req = TborEccGenerateKeyReq { + session_id: session.session_id(), + scope: 0b001, // KeyScope::Session + curve: ECC_CURVE_P256, + }; + let keygen_resp = match ctx.tbor(&keygen_req) { + Ok(resp) => resp, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + // Derive an ECDH shared secret using the key's own pub key as peer. + let ecdh_req = TborEcdhDeriveReq { + session_id: session.session_id(), + scope: 0b001, + masked_key: keygen_resp.masked_key, + peer_pub_key: keygen_resp.pub_key, + }; + let masked_secret = match ctx.tbor(&ecdh_req) { + Ok(resp) => resp.masked_secret, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + let req = TborHkdfDeriveReq { + session_id: session.session_id(), + scope: input.scope, + hash_algo: input.hash_algo, + key_type: input.key_type, + key_length: input.key_length, + masked_secret, + salt: input.salt, + info: input.info, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hmac.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hmac.rs new file mode 100644 index 000000000..3997dff56 --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hmac.rs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::HMAC_HASH_SHA256; +use azihsm_ddi_tbor_types::HMAC_MSG_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborHmacGenerateKeyReq; +use azihsm_ddi_tbor_types::TborHmacReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_msg(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = HMAC_MSG_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + #[arbitrary(with = bounded_msg)] + msg: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + // Generate an HMAC key to obtain a valid masked_key. + let keygen_req = TborHmacGenerateKeyReq { + session_id: session.session_id(), + scope: 0b001, // KeyScope::Session + hash_algo: HMAC_HASH_SHA256, + key_length: 32, + }; + let masked_key = match ctx.tbor(&keygen_req) { + Ok(resp) => resp.masked_key, + Err(_) => { + session.close().expect("session close should succeed"); + return; + } + }; + + let req = TborHmacReq { + session_id: session.session_id(), + masked_key, + msg: input.msg, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hmac_generate_key.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hmac_generate_key.rs new file mode 100644 index 000000000..d4a47dd1c --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_hmac_generate_key.rs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborHmacGenerateKeyReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + hash_algo: u8, + key_length: u8, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborHmacGenerateKeyReq { + session_id: session.session_id(), + scope: input.scope, + hash_algo: input.hash_algo, + key_length: input.key_length, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_rsa_mod_exp.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_rsa_mod_exp.rs new file mode 100644 index 000000000..de11cd89a --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_rsa_mod_exp.rs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::RSA_MASKED_KEY_MAX_LEN; +use azihsm_ddi_tbor_types::RSA_MOD_EXP_MAX_LEN; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::TborRsaModExpReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_masked_key(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = RSA_MASKED_KEY_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +fn bounded_y(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = RSA_MOD_EXP_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + #[arbitrary(with = bounded_masked_key)] + masked_key: Vec, + op_type: u8, + #[arbitrary(with = bounded_y)] + y: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborRsaModExpReq { + session_id: session.session_id(), + masked_key: input.masked_key, + op_type: input.op_type, + y: input.y, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +}); diff --git a/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_unwrap_key.rs b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_unwrap_key.rs new file mode 100644 index 000000000..431d04e3f --- /dev/null +++ b/fuzz/fuzz_targets/ddi/tbor/fuzz_tbor_unwrap_key.rs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#![no_main] + +use azihsm_ddi_tbor_test_harness::TestCtx; +use azihsm_ddi_tbor_types::SessionType; +use azihsm_ddi_tbor_types::UNWRAP_WRAPPED_BLOB_MAX_LEN; +use azihsm_ddi_tbor_types::TborUnwrapKeyReq; +use libfuzzer_sys::arbitrary; +use libfuzzer_sys::arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +const CU: u8 = 1; +static CTX: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn bounded_wrapped_blob(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result> { + let max = UNWRAP_WRAPPED_BLOB_MAX_LEN; + let len = usize::arbitrary(u)? % (max + 1); + Ok(u.bytes(len)?.to_vec()) +} + +#[derive(Arbitrary, Debug)] +struct FuzzInput { + scope: u8, + key_class: u8, + key_usage: u8, + oaep_hash_algo: u8, + #[arbitrary(with = bounded_wrapped_blob)] + wrapped_blob: Vec, +} + +fuzz_target!(|input: FuzzInput| { + let ctx = CTX.get_or_init(TestCtx::new); + ctx.erase().expect("erase should succeed"); + + let session = ctx + .open_session(CU, SessionType::PlainText) + .expect("session open should succeed"); + + let req = TborUnwrapKeyReq { + session_id: session.session_id(), + scope: input.scope, + key_class: input.key_class, + key_usage: input.key_usage, + oaep_hash_algo: input.oaep_hash_algo, + wrapped_blob: input.wrapped_blob, + }; + let _ = ctx.tbor(&req); + + session.close().expect("session close should succeed"); +});