Skip to content

Commit

Permalink
Merge pull request #11 from andrewwhitehead/more-keys
Browse files Browse the repository at this point in the history
0.2.0-pre.4 updates
  • Loading branch information
andrewwhitehead authored May 12, 2021
2 parents 275fb13 + 4349d7d commit 9855e91
Show file tree
Hide file tree
Showing 22 changed files with 760 additions and 228 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["askar-crypto"]

[package]
name = "aries-askar"
version = "0.2.0-pre.3"
version = "0.2.0-pre.4"
authors = ["Hyperledger Aries Contributors <[email protected]>"]
edition = "2018"
description = "Hyperledger Aries Askar secure storage"
Expand Down Expand Up @@ -38,7 +38,7 @@ pg_test = ["postgres"]
hex-literal = "0.3"

[dependencies]
askar-crypto = { version = "0.2.0-pre.3", path = "./askar-crypto", features = ["argon2", "std"] }
askar-crypto = { version = "0.2.0-pre.4", path = "./askar-crypto", features = ["argon2", "std"] }
async-mutex = "1.4"
async-stream = "0.3"
bs58 = "0.4"
Expand Down
2 changes: 1 addition & 1 deletion askar-crypto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "askar-crypto"
version = "0.2.0-pre.3"
version = "0.2.0-pre.4"
authors = ["Hyperledger Aries Contributors <[email protected]>"]
edition = "2018"
description = "Hyperledger Aries Askar cryptography"
Expand Down
23 changes: 13 additions & 10 deletions askar-crypto/src/alg/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl<T: AesAead> KeyAeadInPlace for AesKey<T> {
buffer: &mut dyn ResizeBuffer,
nonce: &[u8],
aad: &[u8],
) -> Result<(), Error> {
) -> Result<usize, Error> {
if nonce.len() != NonceSize::<T>::USIZE {
return Err(err_msg!(InvalidNonce));
}
Expand Down Expand Up @@ -265,7 +265,7 @@ pub trait AesAead: AesType {
buffer: &mut dyn ResizeBuffer,
nonce: &GenericArray<u8, Self::NonceSize>,
aad: &[u8],
) -> Result<(), Error>;
) -> Result<usize, Error>;

/// Perform AEAD decryption
fn aes_decrypt_in_place(
Expand Down Expand Up @@ -293,13 +293,14 @@ where
buffer: &mut dyn ResizeBuffer,
nonce: &GenericArray<u8, Self::NonceSize>,
aad: &[u8],
) -> Result<(), Error> {
) -> Result<usize, Error> {
let enc = <T as NewAead>::new(key);
let tag = enc
.encrypt_in_place_detached(nonce, aad, buffer.as_mut())
.map_err(|_| err_msg!(Encryption, "AEAD encryption error"))?;
let ctext_len = buffer.as_ref().len();
buffer.buffer_write(&tag[..])?;
Ok(())
Ok(ctext_len)
}

fn aes_decrypt_in_place(
Expand Down Expand Up @@ -366,7 +367,7 @@ where
buffer: &mut dyn ResizeBuffer,
nonce: &GenericArray<u8, Self::NonceSize>,
aad: &[u8],
) -> Result<(), Error> {
) -> Result<usize, Error> {
// this should be optimized away except when the error is thrown
if Self::TagSize::USIZE > D::OutputSize::USIZE {
return Err(err_msg!(
Expand Down Expand Up @@ -400,7 +401,7 @@ where
buffer.as_mut()[ctext_end..(ctext_end + Self::TagSize::USIZE)]
.copy_from_slice(&mac[..Self::TagSize::USIZE]);

Ok(())
Ok(ctext_end)
}

fn aes_decrypt_in_place(
Expand Down Expand Up @@ -488,19 +489,21 @@ where
buffer: &mut dyn ResizeBuffer,
_nonce: &GenericArray<u8, Self::NonceSize>,
aad: &[u8],
) -> Result<(), Error> {
) -> Result<usize, Error> {
if aad.len() != 0 {
return Err(err_msg!(Unsupported, "AAD not supported"));
}
if buffer.as_ref().len() % 8 != 0 {
let mut buf_len = buffer.as_ref().len();
if buf_len % 8 != 0 {
return Err(err_msg!(
Unsupported,
"Data length must be a multiple of 8 bytes"
));
}
let blocks = buffer.as_ref().len() / 8;
let blocks = buf_len / 8;

buffer.buffer_insert(0, &[0u8; 8])?;
buf_len += 8;

let aes = K::new(key);
let mut iv = AES_KW_DEFAULT_IV;
Expand All @@ -519,7 +522,7 @@ where
}
}
buffer.as_mut()[0..8].copy_from_slice(&iv[..]);
Ok(())
Ok(buf_len)
}

fn aes_decrypt_in_place(
Expand Down
2 changes: 1 addition & 1 deletion askar-crypto/src/alg/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ impl KeyAeadInPlace for AnyKey {
buffer: &mut dyn ResizeBuffer,
nonce: &[u8],
aad: &[u8],
) -> Result<(), Error> {
) -> Result<usize, Error> {
self.key_as_aead()?.encrypt_in_place(buffer, nonce, aad)
}

Expand Down
5 changes: 3 additions & 2 deletions askar-crypto/src/alg/chacha20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl<T: Chacha20Type> KeyAeadInPlace for Chacha20Key<T> {
buffer: &mut dyn ResizeBuffer,
nonce: &[u8],
aad: &[u8],
) -> Result<(), Error> {
) -> Result<usize, Error> {
if nonce.len() != NonceSize::<T>::USIZE {
return Err(err_msg!(InvalidNonce));
}
Expand All @@ -181,8 +181,9 @@ impl<T: Chacha20Type> KeyAeadInPlace for Chacha20Key<T> {
let tag = chacha
.encrypt_in_place_detached(nonce, aad, buffer.as_mut())
.map_err(|_| err_msg!(Encryption, "AEAD encryption error"))?;
let ctext_len = buffer.as_ref().len();
buffer.buffer_write(&tag[..])?;
Ok(())
Ok(ctext_len)
}

/// Decrypt an encrypted (verification tag appended) value in place
Expand Down
5 changes: 3 additions & 2 deletions askar-crypto/src/encrypt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ pub mod crypto_box;

/// Trait for key types which perform AEAD encryption
pub trait KeyAeadInPlace {
/// Encrypt a secret value in place, appending the verification tag
/// Encrypt a secret value in place, appending the verification tag and
/// returning the length of the ciphertext
fn encrypt_in_place(
&self,
buffer: &mut dyn ResizeBuffer,
nonce: &[u8],
aad: &[u8],
) -> Result<(), Error>;
) -> Result<usize, Error>;

/// Decrypt an encrypted (verification tag appended) value in place
fn decrypt_in_place(
Expand Down
21 changes: 14 additions & 7 deletions src/ffi/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use std::{os::raw::c_char, str::FromStr};

use ffi_support::{rust_string_to_c, ByteBuffer, FfiStr};

use super::{handle::ArcHandle, secret::SecretBuffer, ErrorCode};
use super::{
handle::ArcHandle,
secret::{EncryptedBuffer, SecretBuffer},
ErrorCode,
};
use crate::kms::{
crypto_box, crypto_box_open, crypto_box_random_nonce, crypto_box_seal, crypto_box_seal_open,
derive_key_ecdh_1pu, derive_key_ecdh_es, KeyAlg, LocalKey,
Expand Down Expand Up @@ -275,14 +279,15 @@ pub extern "C" fn askar_key_aead_encrypt(
message: ByteBuffer,
nonce: ByteBuffer,
aad: ByteBuffer,
out: *mut SecretBuffer,
out: *mut EncryptedBuffer,
) -> ErrorCode {
catch_err! {
trace!("AEAD encrypt: {}", handle);
check_useful_c_ptr!(out);
let key = handle.load()?;
let enc = key.aead_encrypt(message.as_slice(), nonce.as_slice(), aad.as_slice())?;
unsafe { *out = SecretBuffer::from_secret(enc) };
let result = EncryptedBuffer::from_encrypted(enc);
unsafe { *out = result };
Ok(ErrorCode::Success)
}
}
Expand All @@ -292,14 +297,15 @@ pub extern "C" fn askar_key_aead_decrypt(
handle: LocalKeyHandle,
ciphertext: ByteBuffer,
nonce: ByteBuffer,
tag: ByteBuffer,
aad: ByteBuffer,
out: *mut SecretBuffer,
) -> ErrorCode {
catch_err! {
trace!("AEAD decrypt: {}", handle);
check_useful_c_ptr!(out);
let key = handle.load()?;
let dec = key.aead_decrypt(ciphertext.as_slice(), nonce.as_slice(), aad.as_slice())?;
let dec = key.aead_decrypt((ciphertext.as_slice(), tag.as_slice()), nonce.as_slice(), aad.as_slice())?;
unsafe { *out = SecretBuffer::from_secret(dec) };
Ok(ErrorCode::Success)
}
Expand Down Expand Up @@ -345,15 +351,15 @@ pub extern "C" fn askar_key_wrap_key(
handle: LocalKeyHandle,
other: LocalKeyHandle,
nonce: ByteBuffer,
out: *mut SecretBuffer,
out: *mut EncryptedBuffer,
) -> ErrorCode {
catch_err! {
trace!("Wrap key: {}", handle);
check_useful_c_ptr!(out);
let key = handle.load()?;
let other = other.load()?;
let result = key.wrap_key(&*other, nonce.as_slice())?;
unsafe { *out = SecretBuffer::from_secret(result) };
unsafe { *out = EncryptedBuffer::from_encrypted(result) };
Ok(ErrorCode::Success)
}
}
Expand All @@ -364,14 +370,15 @@ pub extern "C" fn askar_key_unwrap_key(
alg: FfiStr<'_>,
ciphertext: ByteBuffer,
nonce: ByteBuffer,
tag: ByteBuffer,
out: *mut LocalKeyHandle,
) -> ErrorCode {
catch_err! {
trace!("Unwrap key: {}", handle);
check_useful_c_ptr!(out);
let key = handle.load()?;
let alg = KeyAlg::from_str(alg.as_str())?;
let result = key.unwrap_key(alg, ciphertext.as_slice(), nonce.as_slice())?;
let result = key.unwrap_key(alg, (ciphertext.as_slice(), tag.as_slice()), nonce.as_slice())?;
unsafe { *out = LocalKeyHandle::create(result) };
Ok(ErrorCode::Success)
}
Expand Down
24 changes: 23 additions & 1 deletion src/ffi/secret.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{convert::TryFrom, mem, ptr};

use crate::crypto::buffer::SecretBytes;
use crate::{crypto::buffer::SecretBytes, kms::Encrypted};

#[no_mangle]
pub extern "C" fn askar_buffer_free(buffer: SecretBuffer) {
Expand All @@ -10,6 +10,7 @@ pub extern "C" fn askar_buffer_free(buffer: SecretBuffer) {
}

// Structure consistent with ffi_support ByteBuffer, but zeroized on drop
#[derive(Debug)]
#[repr(C)]
pub struct SecretBuffer {
// must be >= 0, signed int was chosen for compatibility
Expand Down Expand Up @@ -48,3 +49,24 @@ impl SecretBuffer {
}
}
}

// A combined ciphertext and tag value
#[derive(Debug)]
#[repr(C)]
pub struct EncryptedBuffer {
buffer: SecretBuffer,
tag_pos: i64,
nonce_pos: i64,
}

impl EncryptedBuffer {
pub fn from_encrypted(enc: Encrypted) -> Self {
let tag_pos = i64::try_from(enc.tag_pos).expect("ciphertext length exceeds i64::MAX");
let nonce_pos = i64::try_from(enc.nonce_pos).expect("ciphertext length exceeds i64::MAX");
Self {
buffer: SecretBuffer::from_secret(enc.buffer),
tag_pos,
nonce_pos,
}
}
}
106 changes: 106 additions & 0 deletions src/kms/enc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
pub use crate::crypto::buffer::SecretBytes;

/// The result of an AEAD encryption operation
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Encrypted {
pub(crate) buffer: SecretBytes,
pub(crate) tag_pos: usize,
pub(crate) nonce_pos: usize,
}

impl Encrypted {
pub(crate) fn new(buffer: SecretBytes, tag_pos: usize, nonce_pos: usize) -> Self {
Self {
buffer,
tag_pos,
nonce_pos,
}
}

/// Convert the ciphertext and tag into a Vec<u8>
pub fn into_vec(self) -> Vec<u8> {
self.buffer.into_vec()
}

/// Access the ciphertext
pub fn ciphertext(&self) -> &[u8] {
&self.buffer[0..(self.tag_pos)]
}

/// Access the nonce
pub fn nonce(&self) -> &[u8] {
&self.buffer[(self.nonce_pos)..]
}

/// Access the authentication tag
pub fn tag(&self) -> &[u8] {
&self.buffer[(self.tag_pos)..(self.nonce_pos)]
}
}

impl AsRef<[u8]> for Encrypted {
fn as_ref(&self) -> &[u8] {
self.buffer.as_ref()
}
}

impl From<Encrypted> for SecretBytes {
fn from(e: Encrypted) -> Self {
e.buffer
}
}

#[derive(Clone, Copy, Debug)]
/// The payload for an AEAD decryption operation
pub struct ToDecrypt<'d> {
/// The ciphertext to decrypt
pub ciphertext: &'d [u8],
/// The separated AEAD tag, if any
pub tag: &'d [u8],
}

impl<'d> ToDecrypt<'d> {
/// Accessor for the combined length
#[inline]
pub fn len(&self) -> usize {
self.ciphertext.len() + self.tag.len()
}

pub(crate) fn into_secret(self) -> SecretBytes {
if self.tag.is_empty() {
SecretBytes::from_slice(self.ciphertext)
} else {
let mut buf = SecretBytes::with_capacity(self.len());
buf.extend_from_slice(self.ciphertext);
buf.extend_from_slice(self.tag);
buf
}
}
}

impl<'d> From<&'d [u8]> for ToDecrypt<'d> {
fn from(ciphertext: &'d [u8]) -> Self {
Self {
ciphertext,
tag: &[],
}
}
}

impl<'d> From<(&'d [u8], &'d [u8])> for ToDecrypt<'d> {
fn from(split: (&'d [u8], &'d [u8])) -> Self {
Self {
ciphertext: split.0,
tag: split.1,
}
}
}

impl<'d> From<&'d Encrypted> for ToDecrypt<'d> {
fn from(enc: &'d Encrypted) -> Self {
Self {
ciphertext: enc.ciphertext(),
tag: enc.tag(),
}
}
}
Loading

0 comments on commit 9855e91

Please sign in to comment.