diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f914aa16..efb7a39cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,27 @@ jobs: - name: Clippy (no-default-features) run: cargo clippy --all-targets --no-default-features -- -D warnings + zeroization-test: + name: Run the zeroization test + needs: [style] + runs-on: ubuntu-latest + + steps: + - name: Checkout the repo + uses: actions/checkout@v4 + + - name: Install rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: nightly + components: clippy + + - uses: Swatinem/rust-cache@v2 + + - name: Zeroization test + working-directory: ./contrib/zeroization-test + run: make + test: name: ${{ matrix.target.name }} ${{ matrix.channel }} needs: [clippy] diff --git a/.gitignore b/.gitignore index 3b594498f..69294cd54 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ Cargo.lock .gdb_history /afl/*/target /afl/*/out* +/contrib/*/target mutants.out* diff --git a/contrib/zeroization-test/Cargo.toml b/contrib/zeroization-test/Cargo.toml index d3dab95c6..ceda8c68d 100644 --- a/contrib/zeroization-test/Cargo.toml +++ b/contrib/zeroization-test/Cargo.toml @@ -2,12 +2,10 @@ name = "vodozemac-zeroization-test" version = "0.1.0" edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +publish = false [profile.release] debug = true [dependencies] vodozemac = { path = "../.." } -ed25519-dalek = "1.0.1" diff --git a/contrib/zeroization-test/src/main.rs b/contrib/zeroization-test/src/main.rs index f8922e565..d4f2cb679 100644 --- a/contrib/zeroization-test/src/main.rs +++ b/contrib/zeroization-test/src/main.rs @@ -1,16 +1,16 @@ -use vodozemac::cipher::key::ExpandedKeys; +use vodozemac::Ed25519SecretKey; -fn use_keys(_keys: ExpandedKeys) { +fn use_keys(_keys: Ed25519SecretKey) { println!("Point B. Using keys..."); } fn main() { // Used for comparison from inside gdb, to ensure the buffer is zeroized. - let _zero: [u8; 80] = [0u8; 80]; + let _zero = [0u8; 32]; - let secret: [u8; 32] = (0..32).collect::>().try_into().unwrap(); + let secret = [0xFFu8; 32]; println!("Point A. Creating keys..."); - let keys = ExpandedKeys::new(&secret); + let keys = Ed25519SecretKey::from_slice(&secret); use_keys(keys); println!("Point C. `keys` was dropped so buffer should now be zeroized.") } diff --git a/contrib/zeroization-test/test_zeroization.txt b/contrib/zeroization-test/test_zeroization.txt index f000b07df..4ba16be0a 100644 --- a/contrib/zeroization-test/test_zeroization.txt +++ b/contrib/zeroization-test/test_zeroization.txt @@ -1,47 +1,25 @@ -define is_zeroized_partial - set $addr_to_check = $arg0 - - # XXX: $_memeq is broken right now and treats the third argument as the number - # of 4-byte words instead of bytes. - if $_memeq(($addr_to_check as *u8) + 16, $zero, 16) - printf "✅ Object at addr %p partially zeroized (last 64 bytes are zero)\n", $addr_to_check - x/80b $addr_to_check - else - printf "❌ Object at addr %p *NOT* even partially zeroized (last 64 bytes are not zero)\n", $addr_to_check - x/80b $addr_to_check - quit 2 - end -end - -document is_zeroized_partial -Checks whether the object at $arg0 is zeroized. - -Since free writes some stuff to the first 16 bytes of the buffer, this version -only checks that the last 80 - 16 = 64 bytes are zeroized. -end - define is_zeroized_full set $addr_to_check = $arg0 # XXX: $_memeq is broken right now and treats the third argument as the number # of 4-byte words instead of bytes. - if $_memeq($addr_to_check as *u8, $zero, 20) + if $_memeq($addr_to_check as *u8, $zero, 8) printf "✅ Object at addr %p fully zeroized\n", $addr_to_check - x/80b $addr_to_check + x/32bx $addr_to_check else printf "❌ Object at addr %p *NOT* fully zeroized\n", $addr_to_check - x/80b $addr_to_check + x/32bx $addr_to_check quit 1 end end document is_zeroized_full -Checks whether the object at $arg0 is fully zeroized (all of its 80 bytes are +Checks whether the object at $arg0 is fully zeroized (all of its 32 bytes are zero). end # Point B -break use_keys +break vodozemac_zeroization_test::use_keys run @@ -51,11 +29,11 @@ run # We save the address of both the original buffer in the frame above and the # address of the current buffer in `use_keys`. up -set $addr1 = keys.0 +set $addr1 = keys.0.secret_key set $zero = &_zero down -set $addr2 = _keys.0 +set $addr2 = _keys.0.secret_key # Since we've placed the buffer behind a Box, these addresses should be the @@ -73,16 +51,16 @@ end # Then we ensure the buffer is not already all zeros, since that almost surely # indicates that something is wrong. -if $_memeq($addr1, $addr2, 20) +if $_memeq($addr1, $addr2, 32) printf "✅ The objects have the same content.\n" else printf "❌ The objects have *different* content.\n" quit 1 end -if ! $_memeq($addr1, $zero, 20) +if ! $_memeq($addr1, $zero, 32) printf "✅ This content isn't all null bytes.\n" - x/80b $addr1 + x/32bx $addr1 else printf "❌ This content *is* all null bytes.\n" quit 2 @@ -94,20 +72,12 @@ break free break 16 # Proceed to the next `free` call. The object should have already been dropped -# and should be fully zeroized (all 80 bytes). +# and should be fully zeroized (all 32 bytes). continue is_zeroized_full $addr1 is_zeroized_full $addr2 -# Proceed to point C. Since `free` wrote some stuff to the buffer, it should -# now only be partially equal to zero, namely its 64 trailing bytes. Check for -# this. -continue - -is_zeroized_partial $addr1 -is_zeroized_partial $addr2 - # If all was well, we've arrived at this point and the script will finish with # a success exit code. If something went wrong, we've never reached this point # and returned a non-zero exit code.