bouncycastle_core/traits.rs
1//! Provides simplified abstracted APIs over classes of cryptographic primitives, such as Hash, KDF, etc.
2
3use crate::errors::*;
4use crate::key_material::KeyMaterialTrait;
5use core::fmt::{Debug, Display};
6use core::marker::Sized;
7
8// Imports needed for docs
9#[allow(unused_imports)]
10use crate::key_material::KeyMaterial;
11#[allow(unused_imports)]
12use crate::key_material::KeyType;
13// end of imports needed for docs
14
15/// Metadata about a cryptographic algorithm.
16pub trait Algorithm {
17 /// String name for the algorithm, used consistently across the library.
18 const ALG_NAME: &'static str;
19 /// Maximum security strength supported by the algorithm.
20 /// In other words, this algorithm can produce outputs up to this security strength,
21 /// but may produce outputs with lower security strength, for example, if asked to truncate.
22 const MAX_SECURITY_STRENGTH: SecurityStrength;
23}
24
25/// Some algorithms have an assigned OID.
26pub trait AlgorithmOID {
27 /// The OID in component form -- each u32 is one OID component.
28 const OID: &'static [u32];
29 /// The OID in its DER-encoded form.
30 const OID_DER: &'static [u8];
31}
32
33// todo -- split all the SymmetricCipher traits into Encryptor and Decryptor
34/// The basic one-shot encrypt and decrypt that all types of symmetric ciphers must implement.
35/// These are meant to be simple, easy to use, secure, and fool-proof APIs, but they may result in
36/// ciphertexts that are incompatible with other implementations as ciphers in more complex modes, such
37/// as AEADs or stream ciphers may need to stick extra data either at the beginning or end of the ciphertext.
38/// See the documentation of the underlying implementation for more details.
39pub trait SymmetricCipher<const KEY_LEN: usize, const INIT_DATA_LEN: usize>: Algorithm {
40 #[cfg(feature = "std")]
41 /// A one-shot API to encrypt some plaintext with the given key.
42 /// This function returns the ciphertext as a `Vec<u8>`, and therefore is only available when compiling with std.
43 /// Returns a tuple containing the initialization data and the ciphertext.
44 /// This is not available if building for no_std.
45 fn encrypt(
46 key: &KeyMaterial<KEY_LEN>,
47 plaintext: &[u8],
48 ) -> Result<([u8; INIT_DATA_LEN], Vec<u8>), SymmetricCipherError>;
49 /// A one-shot API to encrypt some plaintext with the given key.
50 /// This function takes a reference to the output buffer for the ciphertext, and is therefore available in no_std.
51 /// See the documentation for the underlying implementation for details on providing a ciphertext buffer of sufficient size;
52 /// typically the ciphertext is the same length as the plaintext, but some ciphers may have an expansion factor or require
53 /// extra space for a nonce or tag.
54 /// Returns a tuple containing the initialization data and the number of bytes written to the ciphertext buffer.
55 fn encrypt_out(
56 key: &KeyMaterial<KEY_LEN>,
57 plaintext: &[u8],
58 ciphertext: &mut [u8],
59 ) -> Result<([u8; INIT_DATA_LEN], usize), SymmetricCipherError>;
60 #[cfg(feature = "std")]
61 /// A one-shot API to decrypt some ciphertext with the given key.
62 /// This function returns the ciphertext as a `Vec<u8>`, and therefore is only available when compiling with std.
63 /// This is not available if building for no_std.
64 fn decrypt(
65 key: &KeyMaterial<KEY_LEN>,
66 init_data: [u8; INIT_DATA_LEN],
67 ciphertext: &[u8],
68 ) -> Result<Vec<u8>, SymmetricCipherError>;
69 /// A one-shot API to decrypt some ciphertext with the given key.
70 /// This function takes a reference to the output buffer for the plaintext, and is therefore available in no_std.
71 /// See the documentation for the underlying implementation for details on providing a plaintext buffer of sufficient size;
72 /// typically the ciphertext is the same length as the plaintext, but some ciphers may have an expansion factor or require
73 /// extra space for a nonce or tag.
74 /// Returns a tuple containing the initialization data and the number of bytes written to the plaintext buffer.
75 fn decrypt_out(
76 key: &KeyMaterial<KEY_LEN>,
77 init_data: [u8; INIT_DATA_LEN],
78 ciphertext: &[u8],
79 plaintext: &mut [u8],
80 ) -> Result<usize, SymmetricCipherError>;
81}
82
83/// The basic functions of a block cipher.
84/// This trait allows for a block cipher to generate initialization data, such as an Initialization Vector (IV) or Counter (CTR)
85/// which is not technically part of the ciphertext, but must be transmitted along with the ciphertext in order for the
86/// recipient to perform successful decryption. The length of the initialization data is specified by the implementing struct
87/// via the `INIT_DATA_LEN` constant.
88/// In order for these one-shot APIs to be usable securely in all contexts, the init data will be generated
89/// securely by the block cipher implementation and returned along with the ciphertext, and there is no API for the
90/// user to provide the init data. If you require this functionality, see the documentation for the underlying implementation.
91pub trait BlockCipher<const KEY_LEN: usize, const INIT_DATA_LEN: usize, const BLOCK_LEN: usize>:
92 SymmetricCipher<KEY_LEN, INIT_DATA_LEN> + Sized
93{
94 /// Constructor that begins a flow of the streaming API for encrypting one block at a time.
95 /// Allows for the implementation to return init data such as an IV which is generated prior to encrypting the first block.
96 fn do_encrypt_init(
97 key: &KeyMaterial<KEY_LEN>,
98 ) -> Result<(Self, [u8; INIT_DATA_LEN]), SymmetricCipherError>;
99 /// Encrypts a single block of plaintext.
100 fn do_encrypt_block(
101 &mut self,
102 plaintext: &[u8; BLOCK_LEN],
103 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
104 /// Encrypts a single block of plaintext and writes the ciphertext to the provided buffer.
105 fn do_encrypt_block_out(
106 &mut self,
107 plaintext: &[u8; BLOCK_LEN],
108 ciphertext: &mut [u8; BLOCK_LEN],
109 ) -> Result<usize, SymmetricCipherError>;
110 /// Encrypts the final block of plaintext.
111 fn do_encrypt_final(
112 &mut self,
113 plaintext: &[u8; BLOCK_LEN],
114 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
115 /// Encrypts the final block of plaintext and writes the ciphertext to the provided buffer.
116 fn do_encrypt_final_out(
117 &mut self,
118 plaintext: &[u8; BLOCK_LEN],
119 ciphertext: &mut [u8; BLOCK_LEN],
120 ) -> Result<usize, SymmetricCipherError>;
121 /// Constructor that begins a flow of the streaming API for decryption one block at a time.
122 fn do_decrypt_init(
123 key: &KeyMaterial<KEY_LEN>,
124 init_data: &[u8; INIT_DATA_LEN],
125 ) -> Result<Self, SymmetricCipherError>;
126 /// Decrypts a single block of ciphertext.
127 fn do_decrypt_block(
128 &mut self,
129 ciphertext: &[u8; BLOCK_LEN],
130 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
131 /// Decrypts a single block of ciphertext and writes the plaintext to the provided buffer.
132 fn do_decrypt_block_out(
133 &mut self,
134 ciphertext: &[u8; BLOCK_LEN],
135 plaintext: &mut [u8; BLOCK_LEN],
136 ) -> Result<usize, SymmetricCipherError>;
137 /// Decrypts the final block of ciphertext.
138 /// This is the decryption counterpart to [`BlockCipher::do_encrypt_final`] and is where an
139 /// implementation validates and strips any padding (or otherwise finalizes the flow).
140 fn do_decrypt_final(
141 &mut self,
142 ciphertext: &[u8; BLOCK_LEN],
143 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
144 /// Decrypts the final block of ciphertext and writes the plaintext to the provided buffer.
145 fn do_decrypt_final_out(
146 &mut self,
147 ciphertext: &[u8; BLOCK_LEN],
148 plaintext: &mut [u8; BLOCK_LEN],
149 ) -> Result<usize, SymmetricCipherError>;
150}
151
152/// The basic functions of an Authenticated Encryption with Addititional Data cipher.
153pub trait AEADCipher<const KEY_LEN: usize, const NONCE_LEN: usize, const TAG_LEN: usize>:
154 SymmetricCipher<KEY_LEN, NONCE_LEN> + Sized
155{
156 #[cfg(feature = "std")]
157 /// A one-shot API to encrypt some plaintext with the given key.
158 /// A distinguishing feature of AEAD ciphers is the ability to provide additional authenticated data (AAD)
159 /// that is not encrypted but is protected by the authentication tag; ie it can be sent along with the ciphertext
160 /// and any tampering with it will result in the decryption operation failing the tag check.
161 /// This function returns the ciphertext as a `Vec<u8>`, and therefore is only available when compiling with std.
162 /// Returns a tuple containing a generated nonce, the ciphertext and the tag.
163 fn aead_encrypt(
164 key: &KeyMaterial<KEY_LEN>,
165 aad: &[u8],
166 plaintext: &[u8],
167 ) -> Result<([u8; NONCE_LEN], Vec<u8>, [u8; TAG_LEN]), SymmetricCipherError>;
168 /// A one-shot API to encrypt some plaintext with the given key.
169 /// A distinguishing feature of AEAD ciphers is the ability to provide additional authenticated data (AAD)
170 /// that is not encrypted but is protected by the authentication tag; ie it can be sent along with the ciphertext
171 /// and any tampering with it will result in the decryption operation failing the tag check.
172 /// Returns a tuple containing the randomly-generated nonce, number of bytes written to the ciphertext buffer, and the tag.
173 /// If you need a deterministic mode where you feed in the nonce, use the streaming API of [`BlockCipher`]
174 /// or [`StreamCipher`] as appropriate and feed the nonce into the IV field.
175 fn aead_encrypt_out(
176 key: &KeyMaterial<KEY_LEN>,
177 aad: &[u8],
178 plaintext: &[u8],
179 ciphertext: &mut [u8],
180 ) -> Result<([u8; NONCE_LEN], usize, [u8; TAG_LEN]), SymmetricCipherError>;
181 /// All AEAD ciphers will also be either a [`BlockCipher`] or a [`StreamCipher`], and so will already
182 /// have a streaming API.
183 /// This allows you to finish either style of streaming API flow with AEAD specific do_final()
184 /// that computes and returns the authentication tag.
185 fn do_aead_encrypt_final(self) -> Result<[u8; TAG_LEN], SymmetricCipherError>;
186 #[cfg(feature = "std")]
187 /// A one-shot API to decrypt some ciphertext with the given key.
188 /// This function returns the ciphertext as a `Vec<u8>`, and therefore is only available when compiling with std.
189 fn aead_decrypt(
190 key: &KeyMaterial<KEY_LEN>,
191 nonce: &[u8; NONCE_LEN],
192 aad: &[u8],
193 ciphertext: &[u8],
194 tag: &[u8; TAG_LEN],
195 ) -> Result<Vec<u8>, SymmetricCipherError>;
196 /// A one-shot API to decrypt some ciphertext with the given key.
197 /// This function takes a reference to the output buffer for the plaintext, and is therefore available in no_std.
198 /// See the documentation for the underlying implementation for details on providing a plaintext buffer of sufficient size;
199 /// typically the ciphertext is the same length as the plaintext, but some ciphers may have an expansion factor or require
200 /// extra space for a nonce or tag.
201 /// Returns the number of bytes written to the plaintext buffer.
202 fn aead_decrypt_out(
203 key: &KeyMaterial<KEY_LEN>,
204 nonce: &[u8; NONCE_LEN],
205 aad: &[u8],
206 ciphertext: &[u8],
207 tag: &[u8; TAG_LEN],
208 plaintext: &mut [u8],
209 ) -> Result<usize, SymmetricCipherError>;
210 /// All AEAD ciphers will also be either a [`BlockCipher`] or a [`StreamCipher`], and so will already
211 /// have a streaming API.
212 /// This allows you to finish either style of streaming API flow with AEAD specific do_final()
213 /// that computes and returns the authentication tag.
214 fn do_aead_decrypt_final(self, tag: &[u8; TAG_LEN]) -> Result<(), SymmetricCipherError>;
215}
216
217/// The basic functions of a stream cipher, which differ from those of a block cipher only in that
218/// a stream cipher is assumed to have no underlying block size tied to the implementation, and so the caller gets to specify
219/// the block size for the streaming APIs.
220pub trait StreamCipher<const KEY_LEN: usize, const INIT_DATA_LEN: usize>:
221 SymmetricCipher<KEY_LEN, INIT_DATA_LEN> + Sized
222{
223 /// Constructor that begins a flow of the streaming API for encrypting one block at a time.
224 /// Allows for the implementation to return init data such as an IV which is generated prior to encrypting the first block.
225 fn do_stream_encrypt_init(
226 key: &KeyMaterial<KEY_LEN>,
227 ) -> Result<(Self, [u8; INIT_DATA_LEN]), SymmetricCipherError>;
228 /// Encrypts a single block of plaintext.
229 fn do_stream_encrypt_block<const BLOCK_LEN: usize>(
230 &mut self,
231 plaintext: &[u8; BLOCK_LEN],
232 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
233 /// Encrypts a single block of plaintext and writes the ciphertext to the provided buffer.
234 fn do_stream_encrypt_block_out<const BLOCK_LEN: usize>(
235 &mut self,
236 plaintext: &[u8; BLOCK_LEN],
237 ciphertext: &mut [u8; BLOCK_LEN],
238 ) -> Result<usize, SymmetricCipherError>;
239 /// Encrypts the final block of plaintext.
240 fn do_stream_encrypt_final<const BLOCK_LEN: usize>(
241 &mut self,
242 plaintext: &[u8; BLOCK_LEN],
243 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
244 /// Encrypts the final block of plaintext and writes the ciphertext to the provided buffer.
245 fn do_stream_encrypt_final_out<const BLOCK_LEN: usize>(
246 &mut self,
247 plaintext: &[u8; BLOCK_LEN],
248 ciphertext: &mut [u8; BLOCK_LEN],
249 ) -> Result<usize, SymmetricCipherError>;
250 /// Constructor that begins a flow of the streaming API for decryption one block at a time.
251 fn do_stream_decrypt_init(
252 key: &KeyMaterial<KEY_LEN>,
253 init_data: &[u8; INIT_DATA_LEN],
254 ) -> Result<Self, SymmetricCipherError>;
255 /// Decrypts a single block of ciphertext.
256 fn do_stream_decrypt_block<const BLOCK_LEN: usize>(
257 &mut self,
258 ciphertext: &[u8; BLOCK_LEN],
259 ) -> Result<[u8; BLOCK_LEN], SymmetricCipherError>;
260 /// Decrypts a single block of ciphertext and writes the plaintext to the provided buffer.
261 fn do_stream_decrypt_block_out<const BLOCK_LEN: usize>(
262 &mut self,
263 ciphertext: &[u8; BLOCK_LEN],
264 plaintext: &mut [u8; BLOCK_LEN],
265 ) -> Result<usize, SymmetricCipherError>;
266}
267
268/// A hash function is a cryptographic primitive that takes an input of any length and produces a fixed-size output.
269/// Formally: `H: {0,1}^* -> {0,1}^n`.
270/// A cryptographic hash function will typically satisfy several security properties, including:
271/// * Collision resistance: finding two inputs that yield the same output is computationally difficult.
272/// * Preimage resistance: from a given output, finding an input that generates it is computationally difficult.
273/// * Second preimage resistance: given an input, finding another input that yields the same output is computationally difficult.
274pub trait Hash: Algorithm + Default {
275 /// The size of the internal block in bits -- needed by functions such as HMAC to compute security parameters.
276 fn block_bitlen(&self) -> usize;
277
278 /// The size of the output in bytes.
279 fn output_len(&self) -> usize;
280
281 /// A static one-shot API that hashes the provided data.
282 /// `data` can be of any length, including zero bytes.
283 fn hash(self, data: &[u8]) -> Vec<u8>;
284
285 /// A static one-shot API that hashes the provided data into the provided output slice.
286 /// `data` can be of any length, including zero bytes.
287 /// The entire output buffer is zeroized before the hash output is written.
288 /// The return value is the number of bytes written.
289 fn hash_out(self, data: &[u8], output: &mut [u8]) -> usize;
290
291 /// Provide a chunk of data to be absorbed into the hashes.
292 /// `data` can be of any length, including zero bytes.
293 /// do_update() is intended to be used as part of a streaming interface, and so may by called multiple times.
294 fn do_update(&mut self, data: &[u8]);
295
296 /// Finish absorbing input and produce the hashes output.
297 /// Consumes self, so this must be the final call to this object.
298 fn do_final(self) -> Vec<u8>;
299
300 /// Finish absorbing input and produce the hashes output.
301 /// Consumes self, so this must be the final call to this object.
302 ///
303 /// If the provided buffer is smaller than the hash's output length, the output will be truncated.
304 /// If the provided buffer is larger than the hash's output length, the output will be placed in
305 /// the first [`Hash::output_len`] bytes.
306 /// The entire output buffer is zeroized before the hash output is written, so any bytes past
307 /// [`Hash::output_len`] will be 0.
308 ///
309 /// The return value is the number of bytes written.
310 fn do_final_out(self, output: &mut [u8]) -> usize;
311
312 /// The same as [`Hash::do_final`], but allows for supplying a partial byte as the last input.
313 /// Assumes that the input is in the least significant bits (big endian).
314 fn do_final_partial_bits(
315 self,
316 partial_byte: u8,
317 num_partial_bits: usize,
318 ) -> Result<Vec<u8>, HashError>;
319
320 /// The same as [`Hash::do_final_out`], but allows for supplying a partial byte as the last input.
321 /// Assumes that the input is in the least significant bits (big endian).
322 /// will be placed in the first [`Hash::output_len`] bytes.
323 /// The entire output buffer is zeroized before the hash output is written.
324 /// The return value is the number of bytes written.
325 fn do_final_partial_bits_out(
326 self,
327 partial_byte: u8,
328 num_partial_bits: usize,
329 output: &mut [u8],
330 ) -> Result<usize, HashError>;
331
332 /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
333 fn max_security_strength(&self) -> SecurityStrength;
334}
335
336/// Standard parameters for a hash function.
337pub trait HashAlgParams: Algorithm {
338 /// The fixed output length of the hash function.
339 const OUTPUT_LEN: usize;
340 /// The internal block length of the hash function, which is often used as a meta-parameter for
341 /// determining the security strength of the hash function since this limits the internal
342 /// collision resistance of the hash function.
343 const BLOCK_LEN: usize;
344}
345
346/// A Key Derivation Function (KDF) is a function that takes in one or more input key and some unstructured
347/// additional input, and uses them to produces a derived key.
348pub trait KDF: Default {
349 /// Implementations of this function are capable of deriving an output key from an input key,
350 /// assuming that they have been properly initialized.
351 ///
352 /// # Entropy Conversion rules
353 /// Implementations SHOULD act on a KeyMaterial of any [`KeyType`] and will generally
354 /// return a KeyMaterial of the same type
355 ///
356 /// ex.:
357 ///
358 /// * [`KeyType::Unknown`] -> [`KeyType::Unknown`])
359 /// * [`KeyType::CryptographicRandom`] -> [`KeyType::CryptographicRandom`])
360 /// * [`KeyType::SymmetricCipherKey`] -> [`KeyType::SymmetricCipherKey`])
361 ///
362 /// If provided with an input key, even if it is [`KeyType::CryptographicRandom`], but that
363 /// contains less key material than the internal block size of the KDF, then the KDF
364 /// will not be considered properly seeded, and the output [`KeyMaterial`] will be set to
365 /// [`KeyType::Unknown`] -- for example, seeding SHA3-256 with a [`KeyMaterial`] containing
366 /// only 128 bits of key material.
367 ///
368 /// An implementation can, and in most cases SHOULD, return a [`HashError`] if provided
369 /// with a [`KeyMaterial`] of type [`KeyType::Zeroized`].
370 ///
371 /// # Additional Input
372 /// The `additional_input` parameter is used in deriving the key, but is not credited with any entropy,
373 /// and therefore does not affect the type of the output [`KeyMaterial`].
374 /// This corresponds directly to `FixedInfo` as defined in NIST SP 800-56C.
375 /// The `additional_input` parameter can be empty by passing in `&[0u8; 0]`.
376 ///
377 /// Output length: this function will create a KeyMaterial populated with the default output length
378 /// of the underlying hash primitive.
379 fn derive_key(
380 self,
381 key: &impl KeyMaterialTrait,
382 additional_input: &[u8],
383 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError>;
384
385 /// Same as [`KDF::derive_key`], but fills the provided output [`KeyMaterial`].
386 ///
387 /// Output length: this function will behave differently depending on the underlying hash primitive;
388 /// some, such as SHA2 or SHA3 will produce a fixed-length output, while others, such as SHAKE or HKDF,
389 /// will fill the provided KeyMaterial to capacity and require you to truncate it afterward
390 /// using [`KeyMaterialTrait::set_key_len`].
391 fn derive_key_out(
392 self,
393 key: &impl KeyMaterialTrait,
394 additional_input: &[u8],
395 output_key: &mut impl KeyMaterialTrait,
396 ) -> Result<usize, KDFError>;
397
398 /// Meant to be used for hybrid key establishment schemes or other spit-key scenarios where multiple
399 /// keys need to be combined into a single key of the same length.
400 ///
401 /// This function can also be used to mix a KeyMaterial of low entropy with one of full entropy to
402 /// produce a new full entropy key. For the purposes of determining whether enough input key material
403 /// was provided, the lengths of all full-entropy input keys are added together.
404 ///
405 /// Implementations that are not safe to be used as a split-key PRF MAY still implement this function
406 /// and return a result, but SHOULD set the entropy level of the returned key appropriately; for example
407 /// a KDF that is only full-entropy when keyed in the first input SHOULD return a full entropy key
408 /// only if the first input is full entropy.
409 ///
410 /// Implementations can, and in most cases SHOULD, return a [`KeyMaterial`] of the same type as the
411 /// strongest key, and SHOULD throw a [`HashError`] if all input keys are zeroized.
412 /// For example output a [`KeyType::CryptographicRandom`] key whenever any one of
413 /// the input keys is a [`KeyType::CryptographicRandom`] key.
414 /// As another example, combining a [`KeyType::Unknown`] key with a [`KeyType::MACKey`] key
415 /// should return a [`KeyType::MACKey`].
416 ///
417 /// Output length: this function will create a KeyMaterial populated with the default output length
418 /// of the underlying hash primitive.
419 fn derive_key_from_multiple(
420 self,
421 keys: &[&impl KeyMaterialTrait],
422 additional_input: &[u8],
423 ) -> Result<Box<dyn KeyMaterialTrait>, KDFError>;
424
425 /// Same as [`KDF::derive_key`], but fills the provided output [`KeyMaterial`].
426 ///
427 /// Output length: this function will behave differently depending on the underlying hash primitive;
428 /// some, such as SHA2 or SHA3 will produce a fixed-length output, while others, such as SHAKE or HKDF,
429 /// will fill the provided KeyMaterial to capacity and require you to truncate it afterward
430 /// by using [`KeyMaterialTrait::set_key_len`].
431 fn derive_key_from_multiple_out(
432 self,
433 keys: &[&impl KeyMaterialTrait],
434 additional_input: &[u8],
435 output_key: &mut impl KeyMaterialTrait,
436 ) -> Result<usize, KDFError>;
437
438 /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
439 fn max_security_strength(&self) -> SecurityStrength;
440}
441
442/// A Key Encapsulation Mechanism (KEM) is defined as a set of three operations:
443/// key generation, encapsulation, and decapsulation.
444///
445/// This trait represents the encapsulation operation performed by the holder of the public key.
446/// Decapsulation operations are performed by the corresponding [`KEMDecapsulator`] trait, and key
447/// generation is provided as an inherent associated function directly on the algorithm struct.
448/// There are several reasons for this split: first is architectural; some complex algorithms may
449/// benefit from having the encapsulation and decapsulation implementations split into separate modules.
450/// Second is for compliance: sometimes a policy soft-deprecates an algorithm so that new ciphertexts
451/// can no longer be created, but existing ciphertexts can still be decapsulated. Splitting the traits
452/// makes this policy easier to enforce.
453///
454/// The arrays used to encode public keys, ciphertexts, and shared secrets are statically-sized
455/// because this allows us to safely remove runtime checks for array lengths, which overall reduces
456/// the fallibility of the library. This design choice could make this trait complicated to apply
457/// to a KEM algorithm that does not have fixed sizes for the encodings of these objects.
458pub trait KEMEncapsulator<
459 PK: KEMPublicKey<PK_LEN>,
460 const PK_LEN: usize,
461 const CT_LEN: usize,
462 const SS_LEN: usize,
463>: Sized
464{
465 /// Performs an encapsulation against the given public key.
466 /// Sources randomness from the library's default OS-backed RNG.
467 /// Returns the ciphertext and derived shared secret.
468 fn encaps(pk: &PK) -> Result<(KeyMaterial<SS_LEN>, [u8; CT_LEN]), KEMError>;
469 /// Performs an encapsulation against the given public key.
470 /// Sources randomness from the provided RNG.
471 /// Returns the ciphertext and derived shared secret.
472 fn encaps_rng(
473 pk: &PK,
474 rng: &mut dyn RNG,
475 ) -> Result<(KeyMaterial<SS_LEN>, [u8; CT_LEN]), KEMError>;
476}
477
478/// A Key Encapsulation Mechanism (KEM) is defined as a set of three operations:
479/// key generation, encapsulation, and decapsulation.
480///
481/// This trait represents the decapsulation operation performed by the holder of the private key.
482/// Encapsulation operations are performed by the corresponding [`KEMEncapsulator`] trait, and key
483/// generation is provided as an inherent associated function directly on the algorithm struct.
484/// There are several reasons for this split: first is architectural; some complex algorithms may
485/// benefit from having the encapsulation and decapsulation implementations split into separate modules.
486/// Second is for compliance: sometimes a policy soft-deprecates an algorithm so that new ciphertexts
487/// can no longer be created, but existing ciphertexts can still be decapsulated. Splitting the traits
488/// makes this policy easier to enforce.
489///
490/// The arrays used to encode private keys, ciphertexts, and shared secrets are statically-sized
491/// because this allows us to safely remove runtime checks for array lengths, which overall reduces
492/// the fallibility of the library. This design choice could make this trait complicated to apply
493/// to a KEM algorithm that does not have fixed sizes for the encodings of these objects.
494pub trait KEMDecapsulator<
495 SK: KEMPrivateKey<SK_LEN>,
496 const SK_LEN: usize,
497 const CT_LEN: usize,
498 const SS_LEN: usize,
499>: Sized
500{
501 /// Performs a decapsulation of the given ciphertext.
502 /// Returns the derived shared secret.
503 fn decaps(sk: &SK, ct: &[u8]) -> Result<KeyMaterial<SS_LEN>, KEMError>;
504}
505
506// todo: could the public and private key types impl Into<T: AsRef<[u8]>> and From<T: AsRef<[u8]>>
507// todo: that automatically call the encode and from_bytes() ?
508
509/// A public key for a KEM algorithm, often denoted "pk".
510pub trait KEMPublicKey<const PK_LEN: usize>:
511 PartialEq + Eq + Clone + Debug + Display + Sized
512{
513 /// Write it out to bytes in its standard encoding.
514 fn encode(&self) -> [u8; PK_LEN];
515 /// Write it out to bytes in its standard encoding.
516 /// The entire output buffer is zeroized before the encoding is written.
517 fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize;
518 /// Read it in from bytes in its standard encoding.
519 fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError>;
520}
521
522/// A private key for a KEM algorithm, often denoted "sk" (for "secret key").
523pub trait KEMPrivateKey<const SK_LEN: usize>: PartialEq + Eq + Clone + Sized {
524 /// Write it out to bytes in its standard encoding.
525 fn encode(&self) -> [u8; SK_LEN];
526 /// Write it out to bytes in its standard encoding.
527 /// The entire output buffer is zeroized before the encoding is written.
528 fn encode_out(&self, out: &mut [u8; SK_LEN]) -> usize;
529 /// Read it in from bytes in its standard encoding.
530 fn from_bytes(bytes: &[u8]) -> Result<Self, KEMError>;
531}
532
533/// A Message Authentication Code algorithm is a keyed hash function that behaves somewhat like a symmetric signature function.
534/// A MAC algorithm takes in a key and some data, and produces a MAC (message authentication code) that
535/// can be used to verify the integrity of data.
536///
537/// This trait provides one-shot functions [`MAC::mac`], [`MAC::mac_out`], and [`MAC::verify`].
538/// It also provides streaming functions [`MAC::do_update`], [`MAC::do_final`], [`MAC::do_final_out`],
539/// and [`MAC::do_verify_final`].
540/// The workflow is that a MAC object is initialized with a key with [`MAC::new`] -- or [`MAC::new_allow_weak_key`] if you
541/// need to disable the library's safety mechanism to prevent the use of weak keys -- then data is
542/// processed into one or more calls to [`MAC::do_update`],
543/// after that the object can either create a MAC with [`MAC::do_final`] or [`MAC::do_final_out`] (which are final functions, and so consume the object),
544/// or the object can be used to verify a MAC.
545///
546/// For varifying an existing MAC, it is functionally equivalent to use the provided [`MAC::verify`] and [`MAC::do_verify_final`]
547/// function or to compute a new MAC and compare it to the existing MAC, however the provided verification functions
548/// use constant-time comparison to avoid cryptographic timing attacks whereby an attacker could learn
549/// the bytes of the MAC value under some conditions. Therefore, it is highly recommended to use the provided verification functions.
550///
551/// Note that the MAC key is not represented in this trait because it is provided to the MAC algorithm
552/// as part of its new functions.
553///
554/// MACs do not implement Default because they do not have a sensible no-args constructor.
555pub trait MAC: Sized {
556 /// Create a new MAC instance with the given key.
557 ///
558 /// This is a common constructor whether creating or verifying a MAC value.
559 ///
560 /// Key / Salt is optional, which is indicated by providing an uninitialized KeyMaterial object of length zero,
561 /// the capacity is irrelevant, so KeyMateriol256::new() or KeyMaterial_internal::<0>::new() would both count as an absent salt.
562 ///
563 /// # Note about the security strength of the provided key:
564 /// If you initialize the MAC with a key that is tagged at a lower [`SecurityStrength`] than the
565 /// underlying hash function then [`MAC::new`] will fail with the following error:
566 /// ```text
567 /// MACError::KeyMaterialError(KeyMaterialError::SecurityStrength("HMAC::init(): provided key has a lower security strength than the instantiated HMAC")
568 /// ```
569 /// There are situations in which it is completely reasonable and secure to provide low-entropy
570 /// (and sometimes all-zero) keys / salts; for these cases we have provided [`MAC::new_allow_weak_key`].
571 fn new(key: &impl KeyMaterialTrait) -> Result<Self, MACError>;
572
573 /// Create a new HMAC instance with the given key.
574 ///
575 /// This constructor completely ignores the [`SecurityStrength`] tag on the input key and will "just work".
576 /// This should be used if you really do need to use a weak key, such as an all-zero salt,
577 /// but use of this constructor is discouraged and you should really be asking yourself why you need it;
578 /// in most cases it indicates that your key is not long enough to support the security level of this
579 /// HMAC instance, or the key was derived using algorithms at a lower security level, etc.
580 fn new_allow_weak_key(key: &impl KeyMaterialTrait) -> Result<Self, MACError>;
581
582 /// The size of the output in bytes.
583 fn output_len(&self) -> usize;
584
585 /// One-shot API that computes a MAC for the provided data.
586 /// `data` can be of any length, including zero bytes.
587 ///
588 /// Note about the security strength of the provided key:
589 /// If the provided key is tagged at a lower [`SecurityStrength`] than the instantiated MAC algorithm,
590 /// this will fail with an error:
591 /// ```text
592 /// MACError::KeyMaterialError(KeyMaterialError::SecurityStrength("HMAC::init(): provided key has a lower security strength than the instantiated HMAC")
593 /// ```
594 fn mac(self, data: &[u8]) -> Vec<u8>;
595
596 /// One-shot API that computes a MAC for the provided data and writes it into the provided output slice.
597 /// `data` can be of any length, including zero bytes.
598 ///
599 /// Depending on the underlying MAC implementation, NIST may require that the library enforce
600 /// a minimum length on the mac output value. See documentation for the underlying implementation
601 /// to see conditions under which it throws [`MACError::InvalidLength`].
602 ///
603 /// The entire output buffer is zeroized before the MAC value is written.
604 fn mac_out(self, data: &[u8], out: &mut [u8]) -> Result<usize, MACError>;
605
606 /// One-shot API that verifies a MAC for the provided data.
607 /// `data` can be of any length, including zero bytes.
608 ///
609 /// Internally, this will re-compute the MAC value and then compare it to the provided mac value
610 /// using constant-time comparison. It is highly encouraged to use this utility function instead of
611 /// comparing mac values for equality yourself.
612 ///
613 /// Returns a bool to indicate successful verification of the provided mac value.
614 /// The provided mac value must be an exact match, including length; for example a mac value
615 /// which has been truncated, or which contains extra bytes at the end is considered to not be a match
616 /// and will return false.
617 fn verify(self, data: &[u8], mac: &[u8]) -> bool;
618
619 /// Provide a chunk of data to be absorbed into the MAC.
620 /// `data` can be of any length, including zero bytes.
621 /// do_update() is intended to be used as part of a streaming interface, and so may by called multiple times.
622 fn do_update(&mut self, data: &[u8]);
623
624 /// Finish absorbing input and produce the MAC value.
625 fn do_final(self) -> Vec<u8>;
626
627 /// Depending on the underlying MAC implementation, NIST may require that the library enforce
628 /// a minimum length on the mac output value. See documentation for the underlying implementation
629 /// to see conditions under which it throws [`MACError::InvalidLength`].
630 ///
631 /// The entire output buffer is zeroized before the MAC value is written.
632 fn do_final_out(self, out: &mut [u8]) -> Result<usize, MACError>;
633
634 /// Internally, this will re-compute the MAC value and then compare it to the provided mac value
635 /// using constant-time comparison. It is highly encouraged to use this utility function instead of
636 /// comparing mac values for equality yourself.
637 ///
638 /// Returns a bool to indicate successful verification of the provided mac value.
639 /// The provided mac value must be an exact match, including length; for example a mac value
640 /// which has been truncated, or which contains extra bytes at the end is considered to not be a match
641 /// and will return false.
642 fn do_verify_final(self, mac: &[u8]) -> bool;
643
644 /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
645 fn max_security_strength(&self) -> SecurityStrength;
646}
647
648/// A general indicator used across the library for marking the security level of a cryptographic primitive,
649/// and for tracking the security level of the algorithms that interacted with a given piece of data.
650/// For example, if a KDF at the 128-bit security strength is used to produce a 512-bit key, that key
651/// will also be tagged as having a 128-bit security strength.
652///
653/// Some functions across the library may reject or behave differently based on the security strength
654/// of the inputs they are given. For example a `keygen_from_seed()` may reject a seed taged at a lower
655/// security strength than the one required by the algorithm, or it may proceed, but lower its own
656/// advertised security strength accordingly -- each cryptographic primitive may have additional detail.
657// Dev note: The explicit `#[repr(u8)]` discriminants are the stable on-the-wire encoding used by
658// `SerializableState` implementations (see the corresponding `TryFrom<u8>` impl below).
659// If additional strength levels are added in the future, they can be placed into the enum in
660// any order, but should use currently unassigned values (unless you're doing this on a MAJOR or MINOR
661// release as a breaking change).
662#[derive(Eq, PartialEq, PartialOrd, Clone, Copy, Debug)]
663#[repr(u8)]
664pub enum SecurityStrength {
665 ///
666 None = 0,
667 ///
668 _112bit = 1,
669 ///
670 _128bit = 2,
671 ///
672 _192bit = 3,
673 ///
674 _256bit = 4,
675}
676
677impl TryFrom<u8> for SecurityStrength {
678 type Error = SuspendableError;
679
680 /// Inverse of `self as u8`; rejects unrecognized discriminants with [`SuspendableError::InvalidData`].
681 fn try_from(value: u8) -> Result<Self, Self::Error> {
682 Ok(match value {
683 0 => Self::None,
684 1 => Self::_112bit,
685 2 => Self::_128bit,
686 3 => Self::_192bit,
687 4 => Self::_256bit,
688 _ => return Err(SuspendableError::InvalidData),
689 })
690 }
691}
692
693impl SecurityStrength {
694 /// Rounds down to the closest supported security strength.
695 /// For example, 120-bits is rounded down to 112-bit.
696 pub fn from_bits(bits: usize) -> Self {
697 if bits < 112 {
698 Self::None
699 } else if bits < 128 {
700 Self::_112bit
701 } else if bits < 192 {
702 Self::_128bit
703 } else if bits < 256 {
704 Self::_192bit
705 } else {
706 Self::_256bit
707 }
708 }
709
710 /// Rounds down to the closest supported security strength.
711 /// For example, 15 bytes (120-bits) is rounded down to 112-bit.
712 pub fn from_bytes(bytes: usize) -> Self {
713 Self::from_bits(bytes * 8)
714 }
715
716 /// Outputs the security strength in bits for easier computation.
717 pub fn as_int(&self) -> u32 {
718 match self {
719 Self::None => 0,
720 Self::_112bit => 112,
721 Self::_128bit => 128,
722 Self::_192bit => 192,
723 Self::_256bit => 256,
724 }
725 }
726}
727
728/// An interface for random number generation.
729/// This interface is meant to be simpler and more ergonomic than the interfaces provided by the
730/// `rng` crate, but that one should
731/// be used by applications that intend to submit to FIPS certification as it more closely aligns with the
732/// requirements of SP 800-90A.
733/// Note: this interface produces bytes. If you want a [`KeyMaterialTrait`], then use [`KeyMaterial::from_rng`].
734///
735/// Implementors are expected to also implement [`Default`] (default-construction should produce a
736/// securely OS-seeded instance), but this is intentionally *not* a supertrait bound: requiring
737/// `Default` would make `RNG` not dyn-compatible, and `&mut dyn RNG` is needed so RNG instances
738/// can be handed around as trait objects.
739pub trait RNG {
740 // TODO: add back once we figure out streaming interaction with entropy sources.
741 // fn add_seed_bytes(&mut self, additional_seed: &[u8]) -> Result<(), RNGError>;
742
743 /// Provide additional key material to be mixed in to the existing RNG instance.
744 /// The exact behaviour will be implementation-specific, but this is intended for injecting
745 /// additional entropy, not as the primary method of seeding the RNG.
746 fn add_seed_keymaterial(
747 &mut self,
748 additional_seed: &dyn KeyMaterialTrait,
749 ) -> Result<(), RNGError>;
750 /// Returns the next random 32-bit integer.
751 fn next_int(&mut self) -> Result<u32, RNGError>;
752
753 /// Returns the number of requested bytes.
754 fn next_bytes(&mut self, len: usize) -> Result<Vec<u8>, RNGError>;
755
756 /// Returns the number of bytes written.
757 /// The entire output buffer is zeroized before the random bytes are written.
758 fn next_bytes_out(&mut self, out: &mut [u8]) -> Result<usize, RNGError>;
759
760 /// Fill the provided [`KeyMaterial`] with random bytes.
761 fn fill_keymaterial_out(&mut self, out: &mut dyn KeyMaterialTrait) -> Result<usize, RNGError>;
762
763 /// Returns the Security Strength of this RNG.
764 // todo: we should do a refactor to make [Algorithm] be a `security_strength()` function instead of constant,
765 // then have `RNG: Algorithm`, then delete this function.
766 fn security_strength(&self) -> SecurityStrength;
767}
768
769/// Allows a stateful object to suspend its operation by serializing its state into a byte array
770///so that it can be resumed later, potentially from a different host.
771///
772/// This is intended for situations where an object is being used through its streaming API
773/// (do_update, do_final) and the operation wants to be paused to a cache, for example while waiting
774/// for network IO.
775///
776/// This is not intended as a mechanism to clone the state of an object since in most cases `.clone()`
777/// will be more straightforward.
778///
779/// The serialized state MAY contain short-term sensitive values such as nonces or IVs,
780/// but it MUST NOT include a serialized private key.
781/// Keyed algorithms MUST instead impl
782/// [`SuspendableKeyed`] which requires the key to be supplied independently at the time of deserialization.
783pub trait Suspendable<const SERIALIZED_STATE_LEN: usize>: Sized {
784 /// Suspend operation by serializing out the state of the object.
785 ///
786 /// Note that this consumes `self` to prevent accidentally continuing to use the object after serialization.
787 /// If you want to do this intentionally, then you will need to clone the object before serializing it.
788 ///
789 /// The serialized state MUST include a prefix indicating the version of the library that serialized it.
790 fn suspend(self) -> [u8; SERIALIZED_STATE_LEN];
791
792 /// Resume operation from a serialized state.
793 ///
794 /// Deserializers SHOULD check the version and reject serialized states from incompatible versions
795 /// (including rejecting serializations from a future version of the library).
796 /// For example, if a given object made a breaking change to its serialization in version 1.2.3, then its
797 /// deserializer should reject serialized states from that version or older.
798 fn from_suspended(state: [u8; SERIALIZED_STATE_LEN]) -> Result<Self, SuspendableError>;
799}
800
801/// Similar to [`Suspendable`] in that it allows a stateful object to suspend its operation by
802/// serializing its state into a byte array so that it can be resumed later, potentially from a different host.
803///
804/// The difference is that this trait is for keyed algorithms -- MACs, symmetric ciphers, signatures, etc --
805/// which require a private key in order to resume successfully.
806/// For security reasons, the private key is not included in the serialized state
807/// and must be provided separately as part of the deserialization process.
808pub trait SuspendableKeyed<const SERIALIZED_STATE_LEN: usize>: Sized {
809 /// The type of key that must be re-supplied to resume this object.
810 type Key: ?Sized;
811
812 /// Suspend operation by serializing out the state of the object.
813 ///
814 /// Note that this consumes `self` to prevent accidentally continuing to use the object after serialization.
815 /// If you want to do this intentionally, then you will need to clone the object before serializing it.
816 ///
817 /// The serialized state MUST include a prefix indicating the version of the library that serialized it.
818 fn suspend(self) -> [u8; SERIALIZED_STATE_LEN];
819
820 /// Resume operation from a serialized state and the key.
821 ///
822 /// Deserializers SHOULD check the version and reject serialized states from incompatible versions
823 /// (including rejecting serializations from a future version of the library).
824 /// For example, if a given object made a breaking change to its serialization in version 1.2.3, then its
825 /// deserializer should reject serialized states from that version or older.
826 fn from_suspended(
827 state: [u8; SERIALIZED_STATE_LEN],
828 key: &Self::Key,
829 ) -> Result<Self, SuspendableError>;
830}
831
832/// Pre-Hashed Signer is an extension to [`Signer`] that adds functionality specific to signature
833/// primatives that can operate on a pre-hashed message instead of the full message.
834pub trait PHSigner<
835 PK: SignaturePublicKey<PK_LEN>,
836 SK: SignaturePrivateKey<SK_LEN>,
837 const PK_LEN: usize,
838 const SK_LEN: usize,
839 const SIG_LEN: usize,
840 const PH_LEN: usize,
841>: Signer<SK, SK_LEN, SIG_LEN>
842{
843 /// Produce a signature for the provided pre-hashed message and context.
844 ///
845 /// `ctx` accepts a zero-length byte array.
846 ///
847 /// A note about the `ctx` context parameter:
848 /// This is a newer addition to cryptographic signature primitives. It allows for binding the
849 /// signature to some external property of the application so that a signature will fail to validate
850 /// if removed from its intended context.
851 /// This is particularly useful at preventing content confusion attacks between data formats that
852 /// have very similar data structures, for example S/MIME emails, signed PDFs, and signed executables
853 /// that all use the Cryptographic Message Syntax (CMS) data format, or multiple data objects that
854 /// all use the JWS data format.
855 /// To be properly effective, the ctx value must not be under the control of the attacker, which generally
856 /// means that it needs to be a value that is never transmitted over the wire, but rather is something
857 /// known to the application by context.
858 /// For example, "email" vs "pdf" would be a good choice since the application should know what it is
859 /// attempting to sign or verify.
860 /// The `ctx` param can also be used to bind the signed content to a transaction ID or a username,
861 /// but care should be taken to ensure that an attacker attempting a
862 /// content confusion attack not also cause the signed / verifier to use an incorrect transaction ID or username.
863 ///
864 /// Not all signature primitives will support a context value, so you may need to consult the
865 /// documentation for the underlying primitive for how it handles a ctx in that case, for example, it
866 /// might throw an error, ignore the provided ctx value, or append the ctx to the msg in a non-standard way.
867 fn sign_ph(
868 sk: &SK,
869 ph: &[u8; PH_LEN],
870 ctx: Option<&[u8]>,
871 ) -> Result<[u8; SIG_LEN], SignatureError>;
872 /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
873 /// The entire output buffer is zeroized before the signature is written.
874 fn sign_ph_out(
875 sk: &SK,
876 ph: &[u8; PH_LEN],
877 ctx: Option<&[u8]>,
878 output: &mut [u8; SIG_LEN],
879 ) -> Result<usize, SignatureError>;
880}
881
882/// Pre-Hashed Signature Verifier is an extension to [`SignatureVerifier`] that adds functionality specific to signature
883/// primatives that can operate on a pre-hashed message instead of the full message.
884pub trait PHSignatureVerifier<
885 PK: SignaturePublicKey<PK_LEN>,
886 const PK_LEN: usize,
887 const SIG_LEN: usize,
888 const PH_LEN: usize,
889>: SignatureVerifier<PK, PK_LEN, SIG_LEN>
890{
891 /// On success, returns Ok(())
892 /// On failure, returns Err([`SignatureError::SignatureVerificationFailed`]); may also return other types of [`SignatureError`] as appropriate (such as for invalid-length inputs).
893 fn verify_ph(
894 pk: &PK,
895 ph: &[u8; PH_LEN],
896 ctx: Option<&[u8]>,
897 sig: &[u8],
898 ) -> Result<(), SignatureError>;
899}
900
901// todo: could the public and private key types impl Into<T: AsRef<[u8]>> and From<T: AsRef<[u8]>>
902// todo: that automatically call the encode and from_bytes() ?
903
904/// A public key for a signature algorithm, often denoted "pk".
905pub trait SignaturePublicKey<const PK_LEN: usize>:
906 PartialEq + Eq + Clone + Debug + Display + Sized
907{
908 /// Write it out to bytes in its standard encoding.
909 fn encode(&self) -> [u8; PK_LEN];
910 /// Write it out to bytes in its standard encoding.
911 /// The entire output buffer is zeroized before the encoding is written.
912 fn encode_out(&self, out: &mut [u8; PK_LEN]) -> usize;
913 /// Read it in from bytes in its standard encoding.
914 fn from_bytes(bytes: &[u8]) -> Result<Self, SignatureError>;
915}
916
917/// A private key for a signature algorithm, often denoted "sk" (for "secret key").
918pub trait SignaturePrivateKey<const SK_LEN: usize>: PartialEq + Eq + Clone + Sized {
919 /// Write it out to bytes in its standard encoding.
920 fn encode(&self) -> [u8; SK_LEN];
921 /// Write it out to bytes in its standard encoding.
922 /// The entire output buffer is zeroized before the encoding is written.
923 fn encode_out(&self, out: &mut [u8; SK_LEN]) -> usize;
924 /// Read it in from bytes in its standard encoding.
925 fn from_bytes(bytes: &[u8]) -> Result<Self, SignatureError>;
926}
927
928/// A digital signature algorithm is defined as a set of three operations:
929/// key generation, signing, and verification.
930///
931/// This trait represents the operations performed by the holder of the signing private key:
932/// which include signing and key generation. Verification operations are performed by the corresponding
933/// [`SignatureVerifier`] trait.
934/// There are several reasons for this split: first is architectural; some complex algorithms may
935/// benefit from having the signature generation and verification implementations split into separate modules.
936/// Second is for compliance: sometimes a policy soft-deprecates an algorithm so that new signatures
937/// can no longer be created, but existing signatures can still be verified. Splitting the traits
938/// makes this policy easier to enforce.
939///
940/// This high-level trait defines the operations over a generic signature algorithm that is assumed
941/// to source all its randomness from bouncycastle's default os-backed RNG.
942/// The underlying signature primitives will expose APIs that allow for specifying a specific RNG
943/// or deterministic seed values.
944///
945/// The arrays used to encode public keys, private keys, and signature values are statically-sized
946/// because this allows us to safely remove runtime checks for array lengths, which overall reduces
947/// the fallibility of the library. This design choice could make this trait complicated to apply
948/// to a signature algorithm that do not have fixed sizes for the encodings of these objects.
949pub trait Signer<SK: SignaturePrivateKey<SK_LEN>, const SK_LEN: usize, const SIG_LEN: usize>:
950 Sized
951{
952 /// Produce a signature for the provided message and context.
953 /// Both the `msg` and `ctx` accept zero-length byte arrays.
954 ///
955 /// A note about the `ctx` context parameter:
956 /// This is a newer addition to cryptographic signature primitives. It allows for binding the
957 /// signature to some external property of the application so that a signature will fail to validate
958 /// if removed from its intended context.
959 /// This is particularly useful at preventing content confusion attacks between data formats that
960 /// have very similar data structures, for example S/MIME emails, signed PDFs, and signed executables
961 /// that all use the Cryptographic Message Syntax (CMS) data format, or multiple data objects that
962 /// all use the JWS data format.
963 /// To be properly effective, the ctx value must not be under the control of the attacker, which generally
964 /// means that it needs to be a value that is never transmitted over the wire, but rather is something
965 /// known to the application by context.
966 /// For example, "email" vs "pdf" would be a good choice since the application should know what it is
967 /// attempting to sign or verify.
968 /// The `ctx` param can also be used to bind the signed content to a transaction ID or a username,
969 /// but care should be taken to ensure that an attacker attempting a
970 /// content confusion attack not also cause the signed / verifier to use an incorrect transaction ID or username.
971 ///
972 /// Not all signature primitives will support a context value, so you may need to consult the
973 /// documentation for the underlying primitive for how it handles a ctx in that case, for example, it
974 /// might throw an error, ignore the provided ctx value, or append the ctx to the msg in a non-standard way.
975 fn sign(sk: &SK, msg: &[u8], ctx: Option<&[u8]>) -> Result<[u8; SIG_LEN], SignatureError>;
976
977 /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
978 /// The entire output buffer is zeroized before the signature is written.
979 fn sign_out(
980 sk: &SK,
981 msg: &[u8],
982 ctx: Option<&[u8]>,
983 output: &mut [u8; SIG_LEN],
984 ) -> Result<usize, SignatureError>;
985
986 /* streaming signing API */
987 /// Initialize a signer for streaming mode with the provided private key.
988 fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result<Self, SignatureError>;
989
990 // todo: make this a AsRef<[u8]> ?
991 /// Update the signer with the next chunk of data.
992 /// This can be called multiple times.
993 fn sign_update(&mut self, msg_chunk: &[u8]);
994
995 /// Complete the signing operation. Consumes self.
996 fn sign_final(self) -> Result<[u8; SIG_LEN], SignatureError>;
997
998 /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
999 /// The entire output buffer is zeroized before the signature is written.
1000 fn sign_final_out(self, output: &mut [u8; SIG_LEN]) -> Result<usize, SignatureError>;
1001}
1002
1003/// A digital signature algorithm is defined as a set of three operations:
1004/// key generation, signing, and verification.
1005///
1006/// This trait represents the verification operations performed by the holder of the verification public key.
1007/// Keygen and signing operations are performed by the corresponding [`Signer`] trait.
1008/// There are several reasons for this split: first is architectural; some complex algorithms may
1009/// benefit from having the signature generation and verification implementations split into separate modules.
1010/// Second is for compliance: sometimes a policy soft-deprecates an algorithm so that new signatures
1011/// can no longer be created, but existing signatures can still be verified. Splitting the traits
1012/// makes this policy easier to enforce.
1013///
1014/// Here we statically-size the arrays used to encode public keys, private keys, and signature values
1015/// because this allows us to safely remove runtime checks for array lengths, which overall reduces
1016/// the fallibility of the library. This design choice could make this trait complicated to apply
1017/// to a signature algorithm that do not have fixed sizes for the encodings of these objects.
1018pub trait SignatureVerifier<
1019 PK: SignaturePublicKey<PK_LEN>,
1020 const PK_LEN: usize,
1021 const SIG_LEN: usize,
1022>: Sized
1023{
1024 /// On success, returns Ok(())
1025 /// On failure, returns Err([`SignatureError::SignatureVerificationFailed`]); may also return other types of [`SignatureError`] as appropriate (such as for invalid-length inputs).
1026 fn verify(pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8]) -> Result<(), SignatureError>;
1027
1028 /// streaming verification API
1029 fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result<Self, SignatureError>;
1030
1031 // todo: make this a AsRef<[u8]> ?
1032 /// Update the verifier with the next chunk of data.
1033 /// This can be called multiple times.
1034 fn verify_update(&mut self, msg_chunk: &[u8]);
1035
1036 /// On success, returns Ok(())
1037 /// On failure, returns Err([`SignatureError::SignatureVerificationFailed`]); may also return other types of [`SignatureError`] as appropriate (such as for invalid-length inputs).
1038 fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError>;
1039}
1040
1041/// Extensible Output Functions (XOFs) are similar to hash functions, except that they can produce output of arbitrary length.
1042/// The naming used for the functions of this trait are borrowed from the SHA3-style sponge constructions that split XOF operation
1043/// into two phases: an absorb phase in which an arbitrary amount of input is provided to the XOF,
1044/// and then a squeeze phase in which an arbitrary amount of output is extracted.
1045/// Once squeezing begins, no more input can be absorbed.
1046///
1047/// XOFs are _similar to_ hash functions, but are not hash functions for one technical but important reason:
1048/// since the amount of output to produce is not provided to the XOF in advance, it cannot be used to
1049/// diversify the XOF output streams.
1050/// In other words, the overlapping parts of their outputs will be the same!
1051/// For example, consider two XOFs that absorb the same input data, one that is squeezed to produce 32 bytes,
1052/// and the other to produce 1 kb; both outputs will be identical in their first 32 bytes.
1053/// This could lead to loss of security in a number of ways, for example distinguishing attacks where
1054/// it is sufficient for the attacker to know that two values came from the same input, even if the
1055/// attacker cannot learn what that input was. This is attack is often sufficient, for example,
1056/// to break anonymity-preserving technology.
1057/// Applications that require the arbitrary-length output of an XOF, but also care about these
1058/// distinguishing attacks should consider adding a cryptographic salt to diversify the inputs.
1059pub trait XOF: Default {
1060 /// A static one-shot API that digests the input data and produces `result_len` bytes of output.
1061 fn hash_xof(self, data: &[u8], result_len: usize) -> Vec<u8>;
1062
1063 /// A static one-shot API that digests the input data and produces `result_len` bytes of output.
1064 /// Fills the provided output slice.
1065 /// The entire output buffer is zeroized before the output is written.
1066 fn hash_xof_out(self, data: &[u8], output: &mut [u8]) -> usize;
1067
1068 /// Absorb some amount of input.
1069 fn absorb(&mut self, data: &[u8]) -> Result<(), HashError>;
1070
1071 /// Switches to squeezing.
1072 fn absorb_last_partial_byte(
1073 &mut self,
1074 partial_byte: u8,
1075 num_partial_bits: usize,
1076 ) -> Result<(), HashError>;
1077
1078 /// Can be called multiple times.
1079 fn squeeze(&mut self, num_bytes: usize) -> Vec<u8>;
1080
1081 /// Can be called multiple times.
1082 /// Fills the provided output slice.
1083 /// The entire output buffer is zeroized before the output is written.
1084 fn squeeze_out(&mut self, output: &mut [u8]) -> usize;
1085
1086 /// Squeezes a partial byte from the XOF.
1087 /// Output will be in the top `num_bits` bits of the returned u8 (ie Big Endian).
1088 /// This is a final call and consumes self.
1089 fn squeeze_partial_byte_final(self, num_bits: usize) -> Result<u8, HashError>;
1090
1091 /// The same as [`XOF::squeeze_partial_byte_final`], but writes into the provided output byte.
1092 /// The output byte is zeroized before the result is written.
1093 fn squeeze_partial_byte_final_out(
1094 self,
1095 num_bits: usize,
1096 output: &mut u8,
1097 ) -> Result<(), HashError>;
1098
1099 /// Returns the maximum security strength that this KDF is capable of supporting, based on the underlying primitives.
1100 // todo: we should do a refactor to make [Algorithm] be a `security_strength()` function instead of constant,
1101 // then have `RNG: Algorithm`, then delete this function.
1102 fn max_security_strength(&self) -> SecurityStrength;
1103}