summaryrefslogtreecommitdiff
path: root/src/kms/envelope.rs
diff options
context:
space:
mode:
authorStuart Stock <stuart@int08h.com>2018-10-21 15:04:56 -0500
committerStuart Stock <stuart@int08h.com>2018-10-21 15:04:56 -0500
commit44e6212e3480d2f3b15f30434abc892adcf3836f (patch)
treeddd3e4a80243acb008319c8c8b76bd37fc6516f9 /src/kms/envelope.rs
parentb22a6f055f4578b96224ff2372a0ba0c5942a00f (diff)
downloadroughenough-44e6212e3480d2f3b15f30434abc892adcf3836f.zip
Add tests for envelope cypto and some enums
Diffstat (limited to 'src/kms/envelope.rs')
-rw-r--r--src/kms/envelope.rs121
1 files changed, 120 insertions, 1 deletions
diff --git a/src/kms/envelope.rs b/src/kms/envelope.rs
index 2dc7262..00206de 100644
--- a/src/kms/envelope.rs
+++ b/src/kms/envelope.rs
@@ -126,7 +126,7 @@ impl EnvelopeEncryption {
///
pub fn encrypt_seed(kms: &KmsProvider, plaintext_seed: &[u8]) -> Result<Vec<u8>, KmsError> {
// Generate random DEK and nonce
- let rng = rand::SystemRandom::new();
+ let rng = SystemRandom::new();
let mut dek = [0u8; DEK_SIZE_BYTES];
let mut nonce = [0u8; NONCE_SIZE_BYTES];
rng.fill(&mut dek)?;
@@ -172,3 +172,122 @@ impl EnvelopeEncryption {
Ok(output)
}
}
+
+#[cfg(test)]
+mod test {
+ use hex;
+ use kms::envelope::{DEK_LEN_FIELD, MIN_PAYLOAD_SIZE, NONCE_LEN_FIELD};
+ use kms::EnvelopeEncryption;
+ use kms::{KmsError, KmsProvider};
+ use std::str::FromStr;
+ use std::string::ToString;
+
+ struct MockKmsProvider {}
+
+ // Mock provider that returns a copy of the input
+ impl KmsProvider for MockKmsProvider {
+ fn encrypt_dek(&self, plaintext_dek: &Vec<u8>) -> Result<Vec<u8>, KmsError> {
+ Ok(plaintext_dek.to_vec())
+ }
+
+ fn decrypt_dek(&self, encrypted_dek: &Vec<u8>) -> Result<Vec<u8>, KmsError> {
+ Ok(encrypted_dek.to_vec())
+ }
+ }
+
+ #[test]
+ fn decryption_reject_input_too_short() {
+ let ciphertext_blob = "1234567890";
+ assert!(ciphertext_blob.len() < MIN_PAYLOAD_SIZE);
+
+ let kms = MockKmsProvider {};
+ let result = EnvelopeEncryption::decrypt_seed(&kms, ciphertext_blob.as_bytes());
+
+ match result.expect_err("expected KmsError") {
+ KmsError::InvalidData(msg) => assert!(msg.contains("ciphertext too short")),
+ e => panic!("Unexpected error {:?}", e),
+ }
+ }
+
+ #[test]
+ fn encrypt_decrypt_round_trip() {
+ let kms = MockKmsProvider {};
+ let plaintext = Vec::from("This is the plaintext used for this test 1");
+
+ let enc_result = EnvelopeEncryption::encrypt_seed(&kms, &plaintext);
+ assert_eq!(enc_result.is_ok(), true);
+
+ let ciphertext = enc_result.unwrap();
+ assert_ne!(plaintext, ciphertext);
+
+ let dec_result = EnvelopeEncryption::decrypt_seed(&kms, &ciphertext);
+ assert_eq!(dec_result.is_ok(), true);
+
+ let new_plaintext = dec_result.unwrap();
+ assert_eq!(plaintext, new_plaintext);
+ }
+
+ #[test]
+ fn invalid_dek_length_detected() {
+ let kms = MockKmsProvider {};
+ let plaintext = Vec::from("This is the plaintext used for this test 2");
+
+ let enc_result = EnvelopeEncryption::encrypt_seed(&kms, &plaintext);
+ assert_eq!(enc_result.is_ok(), true);
+
+ let ciphertext = enc_result.unwrap();
+ let mut ciphertext_copy = ciphertext.clone();
+
+ ciphertext_copy[0] = 1;
+ let dec_result = EnvelopeEncryption::decrypt_seed(&kms, &ciphertext_copy);
+ match dec_result.expect_err("expected an error") {
+ KmsError::InvalidData(msg) => assert!(msg.contains("invalid DEK")),
+ e => panic!("unexpected error {:?}", e),
+ }
+ }
+
+ #[test]
+ fn invalid_nonce_length_detected() {
+ let kms = MockKmsProvider {};
+ let plaintext = Vec::from("This is the plaintext used for this test 3");
+
+ let enc_result = EnvelopeEncryption::encrypt_seed(&kms, &plaintext);
+ assert_eq!(enc_result.is_ok(), true);
+
+ let ciphertext = enc_result.unwrap();
+ let mut ciphertext_copy = ciphertext.clone();
+
+ ciphertext_copy[2] = 1;
+ let dec_result = EnvelopeEncryption::decrypt_seed(&kms, &ciphertext_copy);
+ match dec_result.expect_err("expected an error") {
+ KmsError::InvalidData(msg) => assert!(msg.contains("nonce (1)")),
+ e => panic!("unexpected error {:?}", e),
+ }
+ }
+
+ #[test]
+ fn modified_ciphertext_is_detected() {
+ let kms = MockKmsProvider {};
+ let plaintext = Vec::from("This is the plaintext used for this test 4");
+
+ let enc_result = EnvelopeEncryption::encrypt_seed(&kms, &plaintext);
+ assert_eq!(enc_result.is_ok(), true);
+
+ let ciphertext = enc_result.unwrap();
+ assert_ne!(plaintext, ciphertext);
+
+ // start corruption 4 bytes in, after the DEK and NONCE length fields
+ for i in (DEK_LEN_FIELD + NONCE_LEN_FIELD)..ciphertext.len() {
+ let mut ciphertext_copy = ciphertext.clone();
+ // flip some bits
+ ciphertext_copy[i] = ciphertext[i].wrapping_add(1);
+
+ let dec_result = EnvelopeEncryption::decrypt_seed(&kms, &ciphertext_copy);
+
+ match dec_result.expect_err("Expected a KmsError error here") {
+ KmsError::OperationFailed(msg) => assert!(msg.contains("failed to decrypt")),
+ e => panic!("unexpected result {:?}", e),
+ }
+ }
+ }
+}