Skip to content

Commit

Permalink
Benchmark passphrase API of Secure Cell
Browse files Browse the repository at this point in the history
Right now we don't have support for this API in RustThemis so we call
C code directly in decryption benchmark to prepare the input data.

Note that due to the nature of the passphrase API -- KDF makes repeated
invocations purposefully slow -- the benchmarks are abysmally slow too
and we have to cut down the sample sizes to execute them in a resonable
time frame. And we don't need to have much variety in the message size
since execution time is completely dominated by KDF costs until we get
to gigabyte-sized messages.

There is quite a few "inheritance" in the code from master key
benchmarks but I'll leave it around for now until we are sure what
utilities can be shared. Plus, Criterion has issues with reusing code
so we might need to introduce additional helper crates for that which
I would like to avoid doing.
  • Loading branch information
ilammy committed Jan 28, 2020
1 parent af55e03 commit 4e56268
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ jobs:
command: |
cd benches/themis
cargo bench -- 'Secure Cell .* master key/4 KB'
- run:
name: Themis Core - run benchmarks - Secure Cell (passphrase)
command: |
cd benches/themis
# These are awfully slow due to KDF
cargo bench -- 'Secure Cell .* passphrase/4 KB' --sample-size 10
- run:
name: Pack benchmark report
command: |
Expand Down
4 changes: 4 additions & 0 deletions benches/themis/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ criterion = "0.3"
[[bench]]
name = "secure_cell_seal_master_key"
harness = false

[[bench]]
name = "secure_cell_seal_passphrase"
harness = false
2 changes: 1 addition & 1 deletion benches/themis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ You will need Rust toolchain installed to run benchmarks.

| | Master keys | Passphrases |
| ----------------- | ------------- | ------------- |
| Seal |complete | 🛠 WIP |
| Seal |complete | complete |
| Token Protect | 💭 soon | 🛠 WIP |
| Context Imprint | 💭 soon | ➖ N/A |

Expand Down
161 changes: 161 additions & 0 deletions benches/themis/benches/secure_cell_seal_passphrase.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright 2020 Cossack Labs Limited
//
// 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.

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};

use libthemis_sys::{
themis_secure_cell_decrypt_seal_with_passphrase,
themis_secure_cell_encrypt_seal_with_passphrase, THEMIS_BUFFER_TOO_SMALL, THEMIS_SUCCESS,
};

const PASSPHRASE: &str = "correct horse battery staple";
const CONTEXT: &[u8] = b"Themis Core benchmark";
const MIN_AUTH_TOKEN: usize = 128;

const KB: usize = 1024;
const MB: usize = 1024 * KB;
#[allow(clippy::identity_op)]
const MESSAGE_SIZES: &[usize] = &[
// There is no significant difference between those due to KDF
64, // cache line (and close to EcdsaPrivateKey)
4 * KB, // memory page
1 * MB, // L2 cache
];

pub fn encryption(c: &mut Criterion) {
let mut group = c.benchmark_group("Secure Cell encryption - Seal, passphrase");
for message_size in MESSAGE_SIZES {
group.throughput(Throughput::Bytes(*message_size as u64));
group.bench_with_input(
BenchmarkId::from_parameter(pretty(*message_size)),
message_size,
|b, &size| {
let message = vec![0; size];

let mut encrypted = vec![0; size + MIN_AUTH_TOKEN];
b.iter(|| {
let mut encrypted_size = 0;
let res = unsafe {
themis_secure_cell_encrypt_seal_with_passphrase(
PASSPHRASE.as_ptr(),
PASSPHRASE.len(),
CONTEXT.as_ptr(),
CONTEXT.len(),
message.as_ptr(),
message.len(),
std::ptr::null_mut(),
&mut encrypted_size,
)
};
assert_eq!(res, THEMIS_BUFFER_TOO_SMALL as i32);
assert!(encrypted_size <= encrypted.len());

let res = unsafe {
themis_secure_cell_encrypt_seal_with_passphrase(
PASSPHRASE.as_ptr(),
PASSPHRASE.len(),
CONTEXT.as_ptr(),
CONTEXT.len(),
message.as_ptr(),
message.len(),
encrypted.as_mut_ptr(),
&mut encrypted_size,
)
};
assert_eq!(res, THEMIS_SUCCESS as i32);
});
},
);
}
group.finish();
}

pub fn decryption(c: &mut Criterion) {
let mut group = c.benchmark_group("Secure Cell decryption - Seal, passphrase");
for message_size in MESSAGE_SIZES {
group.throughput(Throughput::Bytes(*message_size as u64));
group.bench_with_input(
BenchmarkId::from_parameter(pretty(*message_size)),
message_size,
|b, &size| {
let message = vec![0; size];
// TODO: replace with themis::SecureCell when passphrase API is available
let mut encrypted = vec![0; size + MIN_AUTH_TOKEN];
let mut encrypted_size = encrypted.len();
let res = unsafe {
themis_secure_cell_encrypt_seal_with_passphrase(
PASSPHRASE.as_ptr(),
PASSPHRASE.len(),
CONTEXT.as_ptr(),
CONTEXT.len(),
message.as_ptr(),
message.len(),
encrypted.as_mut_ptr(),
&mut encrypted_size,
)
};
assert_eq!(res, THEMIS_SUCCESS as i32);
encrypted.truncate(encrypted_size);
let encrypted = encrypted;

let mut decrypted = vec![0; size];
b.iter(|| {
let mut decrypted_size = 0;
let res = unsafe {
themis_secure_cell_decrypt_seal_with_passphrase(
PASSPHRASE.as_ptr(),
PASSPHRASE.len(),
CONTEXT.as_ptr(),
CONTEXT.len(),
encrypted.as_ptr(),
encrypted.len(),
std::ptr::null_mut(),
&mut decrypted_size,
)
};
assert_eq!(res, THEMIS_BUFFER_TOO_SMALL as i32);
assert!(decrypted_size <= decrypted.len());

let res = unsafe {
themis_secure_cell_decrypt_seal_with_passphrase(
PASSPHRASE.as_ptr(),
PASSPHRASE.len(),
CONTEXT.as_ptr(),
CONTEXT.len(),
encrypted.as_ptr(),
encrypted.len(),
decrypted.as_mut_ptr(),
&mut decrypted_size,
)
};
assert_eq!(res, THEMIS_SUCCESS as i32);
});
},
);
}
group.finish();
}

fn pretty(size: usize) -> String {
if size >= MB {
format!("{} MB", size / MB)
} else if size >= KB {
format!("{} KB", size / KB)
} else {
format!("{}", size)
}
}

criterion_group!(benches, encryption, decryption);
criterion_main!(benches);

0 comments on commit 4e56268

Please sign in to comment.