1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use crate::memguard::SecretBytes;
use crate::secrets_store_capnp::{block, KeyDerivationType, KeyType};

use super::SecretStoreResult;

#[cfg(feature = "openssl")]
mod openssl_rsa_aes_gcm;
mod rust_argon2id;
#[cfg(feature = "rust_crypto")]
mod rust_rsa_aes_gcm;
mod rust_x25519_chacha20_poly1305;

#[cfg(feature = "openssl")]
pub use self::openssl_rsa_aes_gcm::OPEN_SSL_RSA_AES_GCM;
pub use self::rust_argon2id::RUST_ARGON2_ID;
#[cfg(feature = "rust_crypto")]
pub use self::rust_rsa_aes_gcm::RUST_RSA_AES_GCM;
pub use self::rust_x25519_chacha20_poly1305::RUST_X25519CHA_CHA20POLY1305;

#[cfg(test)]
mod fixture_tests;
#[cfg(test)]
mod tests;

pub type PublicKey = Vec<u8>;
pub type PrivateKey = SecretBytes;
type PublicData = Vec<u8>;
type PrivateData = SecretBytes;
type SealKey = SecretBytes;

/// Common interface of all cipher suites.
///
/// In this case "Chiper" does not refer to a single cipher but rather to a set of
/// chiphers and methods used in combination to realize public/private key encryption
/// on data with multiple recipients.
///
pub trait Cipher: Send + Sync {
  /// Get the type identifier use inside the storage format.
  fn key_type(&self) -> KeyType;

  /// Get a displayable name of the cipher
  fn name(&self) -> String;

  /// Generate a new public-private key-pair.
  ///
  /// The cipher should decide by itself a suitable key-strength.
  ///
  fn generate_key_pair(&self) -> SecretStoreResult<(PublicKey, PrivateKey)>;

  /// Get the required length of the seal key for the `seal_private_key` and `open_private_key` operation.
  fn seal_key_length(&self) -> usize;

  /// Get the minimal nonce length for all seal/open/encrypt/decrypt operations.
  fn seal_min_nonce_length(&self) -> usize;

  /// Seal a private key of this cipher suite.
  ///
  /// * `seal_key` the sealing key created by a key-derivation, ensured to have exactly `seal_key_length` bytes
  /// * `nonce` random nonce to use, ensured to have at least `seal_min_nonce_length` bytes
  /// * `private_key` the private key to seal, created by a `generate_key_pair` of this suite
  ///
  fn seal_private_key(
    &self,
    seal_key: &SealKey,
    nonce: &[u8],
    private_key: &PrivateKey,
  ) -> SecretStoreResult<PublicData>;

  /// Open a sealed private key of this cipher suite.
  ///
  /// * `seal_key` the sealing key created by a key-derivation, ensured to have exactly `seal_key_length` bytes
  /// * `nonce` random nonce to use, ensured to have at least `seal_min_nonce_length` bytes
  /// * `crypted_key` the encrypted bytes created by a `seal_private_key`
  ///
  fn open_private_key(&self, seal_key: &SealKey, nonce: &[u8], crypted_key: &[u8]) -> SecretStoreResult<PrivateKey>;

  /// Encrypt arbitrary data for a set of recipients.
  ///
  /// * `recipients` list of recipients allowed to access/decrypt the data. It has to be
  ///   ensured that each recipient contains a public-key compatible with this suite.
  /// * `data` the data to encrypt
  /// * `header_builder` reference to the builder creating the encapsulating data-block for
  ///   storage
  ///
  fn encrypt(
    &self,
    recipients: &[(&str, PublicKey)],
    data: &PrivateData,
    header_builder: block::header::Builder,
  ) -> SecretStoreResult<PublicData>;

  /// Decrypt data for a user
  ///
  /// * `user` the user accessing/decrypting the data. It has to be ensured that the user
  ///   contains a private-key compatible with this suite and is part of the recipient list
  ///   of the data.
  /// * `header` reference to the header of the stored data-block.
  /// * `crypted` the encrypted data
  ///
  fn decrypt(
    &self,
    user: (&str, &PrivateKey),
    header: block::header::Reader,
    crypted: &[u8],
  ) -> SecretStoreResult<PrivateData>;

  fn find_matching_header<'a>(
    &self,
    headers: &capnp::struct_list::Reader<'a, block::header::Owned>,
  ) -> SecretStoreResult<Option<block::header::Reader<'a>>> {
    for header in headers.iter() {
      if header.get_type()? == self.key_type() {
        return Ok(Some(header));
      }
    }
    Ok(None)
  }
}

/// Common interface for a key-derivation method.
///
/// An implmentation of KeyDerivation is used to derive the seal-key of a Cipher.
///
/// Each method may have multiple presets for internal parameters that have to be adjusted to
/// common CPU power and use-case. Each preset is identified by a simple number.
///
pub trait KeyDerivation: Send + Sync {
  /// Get the key derivation type of the implmenetation.
  fn key_derivation_type(&self) -> KeyDerivationType;

  /// Get the default preset to use (for new keys).
  fn default_preset(&self) -> u8;

  /// Get the minmal length of a nonce for key-derivation.
  fn min_nonce_len(&self) -> usize;

  /// Derive a seal-key from a passphrase.
  ///
  /// * `passphrase` provided by the user
  /// * `preset` key-derivation preset to use
  /// * `nonce` random nonce to use, ensured to have at least `min_nonce_len` bytes
  /// * `key_length` the required key-length of the seal-key. The output must have exactly
  ///   this length.
  ///
  fn derive(&self, passphrase: &SecretBytes, preset: u8, nonce: &[u8], key_length: usize)
    -> SecretStoreResult<SealKey>;
}