-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PM-5693] CryptoService using memfd_secret on Linux #7
base: main
Are you sure you want to change the base?
Changes from all commits
d7c7c3e
6068e84
50dc1b4
216eb25
4b846ed
7a01168
c649bf0
b901ef7
e2129ad
f708fcc
30854f7
bed894a
709dfce
f7eda88
ce2343e
bcd712f
38343d2
f34ce02
cc27320
281619d
32d298f
c43aa08
dd37d1d
45f3d32
1f70169
22a8b17
c63f656
db3f8d4
eb81684
d279626
d5f1ede
8652d79
fdb0263
6ea6267
32088c7
f882fb2
bec4786
c2ffea6
c0d2b63
cacf4db
f4ca816
748ba75
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,10 @@ pub enum CryptoError { | |
MissingKey(Uuid), | ||
#[error("The item was missing a required field: {0}")] | ||
MissingField(&'static str), | ||
#[error("Missing Key for Ref. {0}")] | ||
MissingKey2(String), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's removed in the other PR that starts using this code in the rest of the SDK: I didn't want to update it here to avoid needing to touch up code which was going to need to be updated in the other PR anyway |
||
#[error("Crypto store is read-only")] | ||
ReadOnlyCryptoStore, | ||
|
||
#[error("Insufficient KDF parameters")] | ||
InsufficientKdfParameters, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
use super::key_ref::{AsymmetricKeyRef, KeyRef, SymmetricKeyRef}; | ||
use crate::{service::CryptoServiceContext, AsymmetricEncString, CryptoError, EncString}; | ||
|
||
/// This trait should be implemented by any struct capable of knowing which key it needs | ||
/// to encrypt or decrypt itself. | ||
pub trait UsesKey<Key: KeyRef> { | ||
fn uses_key(&self) -> Key; | ||
} | ||
|
||
pub trait Encryptable< | ||
SymmKeyRef: SymmetricKeyRef, | ||
AsymmKeyRef: AsymmetricKeyRef, | ||
Key: KeyRef, | ||
Output, | ||
> | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: Key, | ||
) -> Result<Output, crate::CryptoError>; | ||
} | ||
|
||
pub trait Decryptable< | ||
SymmKeyRef: SymmetricKeyRef, | ||
AsymmKeyRef: AsymmetricKeyRef, | ||
Key: KeyRef, | ||
Output, | ||
> | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: Key, | ||
) -> Result<Output, crate::CryptoError>; | ||
} | ||
|
||
// Basic Encryptable/Decryptable implementations to and from bytes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these be doc comments? |
||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Decryptable<SymmKeyRef, AsymmKeyRef, SymmKeyRef, Vec<u8>> for EncString | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: SymmKeyRef, | ||
) -> Result<Vec<u8>, crate::CryptoError> { | ||
ctx.decrypt_data_with_symmetric_key(key, self) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Decryptable<SymmKeyRef, AsymmKeyRef, AsymmKeyRef, Vec<u8>> for AsymmetricEncString | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: AsymmKeyRef, | ||
) -> Result<Vec<u8>, crate::CryptoError> { | ||
ctx.decrypt_data_with_asymmetric_key(key, self) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Encryptable<SymmKeyRef, AsymmKeyRef, SymmKeyRef, EncString> for &[u8] | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: SymmKeyRef, | ||
) -> Result<EncString, crate::CryptoError> { | ||
ctx.encrypt_data_with_symmetric_key(key, self) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Encryptable<SymmKeyRef, AsymmKeyRef, AsymmKeyRef, AsymmetricEncString> for &[u8] | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: AsymmKeyRef, | ||
) -> Result<AsymmetricEncString, crate::CryptoError> { | ||
ctx.encrypt_data_with_asymmetric_key(key, self) | ||
} | ||
} | ||
|
||
// Encryptable/Decryptable implementations to and from strings | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Decryptable<SymmKeyRef, AsymmKeyRef, SymmKeyRef, String> for EncString | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: SymmKeyRef, | ||
) -> Result<String, crate::CryptoError> { | ||
let bytes: Vec<u8> = self.decrypt(ctx, key)?; | ||
String::from_utf8(bytes).map_err(|_| CryptoError::InvalidUtf8String) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Decryptable<SymmKeyRef, AsymmKeyRef, AsymmKeyRef, String> for AsymmetricEncString | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: AsymmKeyRef, | ||
) -> Result<String, crate::CryptoError> { | ||
let bytes: Vec<u8> = self.decrypt(ctx, key)?; | ||
String::from_utf8(bytes).map_err(|_| CryptoError::InvalidUtf8String) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Encryptable<SymmKeyRef, AsymmKeyRef, SymmKeyRef, EncString> for &str | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: SymmKeyRef, | ||
) -> Result<EncString, crate::CryptoError> { | ||
self.as_bytes().encrypt(ctx, key) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Encryptable<SymmKeyRef, AsymmKeyRef, AsymmKeyRef, AsymmetricEncString> for &str | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: AsymmKeyRef, | ||
) -> Result<AsymmetricEncString, crate::CryptoError> { | ||
self.as_bytes().encrypt(ctx, key) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Encryptable<SymmKeyRef, AsymmKeyRef, SymmKeyRef, EncString> for String | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: SymmKeyRef, | ||
) -> Result<EncString, crate::CryptoError> { | ||
self.as_bytes().encrypt(ctx, key) | ||
} | ||
} | ||
|
||
impl<SymmKeyRef: SymmetricKeyRef, AsymmKeyRef: AsymmetricKeyRef> | ||
Encryptable<SymmKeyRef, AsymmKeyRef, AsymmKeyRef, AsymmetricEncString> for String | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: AsymmKeyRef, | ||
) -> Result<AsymmetricEncString, crate::CryptoError> { | ||
self.as_bytes().encrypt(ctx, key) | ||
} | ||
} | ||
|
||
// Generic implementations for Optional values | ||
|
||
impl< | ||
SymmKeyRef: SymmetricKeyRef, | ||
AsymmKeyRef: AsymmetricKeyRef, | ||
Key: KeyRef, | ||
T: Encryptable<SymmKeyRef, AsymmKeyRef, Key, Output>, | ||
Output, | ||
> Encryptable<SymmKeyRef, AsymmKeyRef, Key, Option<Output>> for Option<T> | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: Key, | ||
) -> Result<Option<Output>, crate::CryptoError> { | ||
self.as_ref() | ||
.map(|value| value.encrypt(ctx, key)) | ||
.transpose() | ||
} | ||
} | ||
|
||
impl< | ||
SymmKeyRef: SymmetricKeyRef, | ||
AsymmKeyRef: AsymmetricKeyRef, | ||
Key: KeyRef, | ||
T: Decryptable<SymmKeyRef, AsymmKeyRef, Key, Output>, | ||
Output, | ||
> Decryptable<SymmKeyRef, AsymmKeyRef, Key, Option<Output>> for Option<T> | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: Key, | ||
) -> Result<Option<Output>, crate::CryptoError> { | ||
self.as_ref() | ||
.map(|value| value.decrypt(ctx, key)) | ||
.transpose() | ||
} | ||
} | ||
|
||
// Generic implementations for Vec values | ||
|
||
impl< | ||
SymmKeyRef: SymmetricKeyRef, | ||
AsymmKeyRef: AsymmetricKeyRef, | ||
Key: KeyRef, | ||
T: Encryptable<SymmKeyRef, AsymmKeyRef, Key, Output>, | ||
Output, | ||
> Encryptable<SymmKeyRef, AsymmKeyRef, Key, Vec<Output>> for Vec<T> | ||
{ | ||
fn encrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: Key, | ||
) -> Result<Vec<Output>, crate::CryptoError> { | ||
self.iter().map(|value| value.encrypt(ctx, key)).collect() | ||
} | ||
} | ||
|
||
impl< | ||
SymmKeyRef: SymmetricKeyRef, | ||
AsymmKeyRef: AsymmetricKeyRef, | ||
Key: KeyRef, | ||
T: Decryptable<SymmKeyRef, AsymmKeyRef, Key, Output>, | ||
Output, | ||
> Decryptable<SymmKeyRef, AsymmKeyRef, Key, Vec<Output>> for Vec<T> | ||
{ | ||
fn decrypt( | ||
&self, | ||
ctx: &mut CryptoServiceContext<SymmKeyRef, AsymmKeyRef>, | ||
key: Key, | ||
) -> Result<Vec<Output>, crate::CryptoError> { | ||
self.iter().map(|value| value.decrypt(ctx, key)).collect() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use crate::{AsymmetricCryptoKey, SymmetricCryptoKey}; | ||
|
||
// Hide the `KeyRef` trait from the public API, to avoid confusion | ||
// the trait itself needs to be public to reference it in the macro, so wrap it in a hidden module | ||
#[doc(hidden)] | ||
pub mod __internal { | ||
use std::{fmt::Debug, hash::Hash}; | ||
|
||
use zeroize::ZeroizeOnDrop; | ||
|
||
use crate::CryptoKey; | ||
|
||
/// This trait represents a key reference that can be used to identify cryptographic keys in the | ||
/// key store. It is used to abstract over the different types of keys that can be used in | ||
/// the system, an end user would not implement this trait directly, and would instead use | ||
/// the `SymmetricKeyRef` and `AsymmetricKeyRef` traits. | ||
pub trait KeyRef: | ||
Debug + Clone + Copy + Hash + Eq + PartialEq + Ord + PartialOrd + Send + Sync + 'static | ||
{ | ||
type KeyValue: CryptoKey + Send + Sync + ZeroizeOnDrop; | ||
|
||
/// Returns whether the key is local to the current context or shared globally by the | ||
/// service. | ||
fn is_local(&self) -> bool; | ||
} | ||
} | ||
pub(crate) use __internal::KeyRef; | ||
|
||
// These traits below are just basic aliases of the `KeyRef` trait, but they allow us to have two | ||
// separate trait bounds | ||
|
||
pub trait SymmetricKeyRef: KeyRef<KeyValue = SymmetricCryptoKey> {} | ||
pub trait AsymmetricKeyRef: KeyRef<KeyValue = AsymmetricCryptoKey> {} | ||
|
||
// Just a small derive_like macro that can be used to generate the key reference enums. | ||
// Example usage: | ||
// ```rust | ||
// key_refs! { | ||
// #[symmetric] | ||
// pub enum KeyRef { | ||
// User, | ||
// Org(Uuid), | ||
// #[local] | ||
// Local(String), | ||
// } | ||
// } | ||
#[macro_export] | ||
macro_rules! key_refs { | ||
( $( | ||
#[$meta_type:tt] | ||
$(pub)? enum $name:ident { | ||
$( | ||
$( #[$variant_tag:tt] )? | ||
$variant:ident $( ( $inner:ty ) )? | ||
,)+ | ||
} | ||
)+ ) => { $( | ||
#[derive(std::fmt::Debug, Clone, Copy, std::hash::Hash, Eq, PartialEq, Ord, PartialOrd)] | ||
pub enum $name { $( | ||
$variant $( ($inner) )? | ||
,)+ } | ||
|
||
impl $crate::key_ref::__internal::KeyRef for $name { | ||
type KeyValue = key_refs!(@key_type $meta_type); | ||
|
||
fn is_local(&self) -> bool { | ||
use $name::*; | ||
match self { $( | ||
key_refs!(@variant_match $variant $( ( $inner ) )?) => | ||
key_refs!(@variant_tag $( $variant_tag )? ), | ||
)+ } | ||
} | ||
} | ||
|
||
key_refs!(@key_trait $meta_type $name); | ||
)+ }; | ||
|
||
( @key_type symmetric ) => { $crate::SymmetricCryptoKey }; | ||
( @key_type asymmetric ) => { $crate::AsymmetricCryptoKey }; | ||
|
||
( @key_trait symmetric $name:ident ) => { impl $crate::key_ref::SymmetricKeyRef for $name {} }; | ||
( @key_trait asymmetric $name:ident ) => { impl $crate::key_ref::AsymmetricKeyRef for $name {} }; | ||
|
||
( @variant_match $variant:ident ( $inner:ty ) ) => { $variant (_) }; | ||
( @variant_match $variant:ident ) => { $variant }; | ||
|
||
( @variant_tag local ) => { true }; | ||
( @variant_tag ) => { false }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should try and get this merged upstream.