mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-28 06:23:08 -08:00
update KEM trait
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1828,6 +1828,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"rosenpass-oqs",
|
"rosenpass-oqs",
|
||||||
"rosenpass-secret-memory",
|
"rosenpass-secret-memory",
|
||||||
|
"thiserror 2.0.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ repository = "https://github.com/rosenpass/rosenpass"
|
|||||||
readme = "readme.md"
|
readme = "readme.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
thiserror = "2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rosenpass-oqs = { workspace = true }
|
rosenpass-oqs = { workspace = true }
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
mod primitives;
|
mod primitives;
|
||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
|
|
||||||
mod kem;
|
|
||||||
pub use kem::Kem;
|
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
pub mod kem;
|
||||||
pub mod keyed_hash;
|
pub mod keyed_hash;
|
||||||
|
|||||||
171
cipher-traits/src/primitives/kem.rs
Normal file
171
cipher-traits/src/primitives/kem.rs
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
//! Traits and implementations for Key Encapsulation Mechanisms (KEMs)
|
||||||
|
//!
|
||||||
|
//! KEMs are the interface provided by almost all post-quantum
|
||||||
|
//! secure key exchange mechanisms.
|
||||||
|
//!
|
||||||
|
//! Conceptually KEMs are akin to public-key encryption, but instead of encrypting
|
||||||
|
//! arbitrary data, KEMs are limited to the transmission of keys, randomly chosen during
|
||||||
|
//! encapsulation.
|
||||||
|
//!
|
||||||
|
//! The [Kem] Trait describes the basic API offered by a Key Encapsulation
|
||||||
|
//! Mechanism. Two implementations for it are provided:
|
||||||
|
//! [Kyber512](../../rosenpass_oqs/kyber_512/enum.Kyber512.html) and
|
||||||
|
//! [ClassicMceliece460896](../../rosenpass_oqs/classic_mceliece_460896/enum.ClassicMceliece460896.html).
|
||||||
|
//!
|
||||||
|
//! An example where Alice generates a keypair and gives her public key to Bob, for Bob to
|
||||||
|
//! encapsulate a symmetric key and Alice to decapsulate it would look as follows.
|
||||||
|
//! In the example, we are using Kyber512, but any KEM that correctly implements the [Kem]
|
||||||
|
//! trait could be used as well.
|
||||||
|
//!```rust
|
||||||
|
//! use rosenpass_cipher_traits::Kem;
|
||||||
|
//! use rosenpass_oqs::Kyber512;
|
||||||
|
//! # use rosenpass_secret_memory::{secret_policy_use_only_malloc_secrets, Secret};
|
||||||
|
//!
|
||||||
|
//! type MyKem = Kyber512;
|
||||||
|
//! secret_policy_use_only_malloc_secrets();
|
||||||
|
//! let mut alice_sk: Secret<{ MyKem::SK_LEN }> = Secret::zero();
|
||||||
|
//! let mut alice_pk: [u8; MyKem::PK_LEN] = [0; MyKem::PK_LEN];
|
||||||
|
//! MyKem::keygen(alice_sk.secret_mut(), &mut alice_pk)?;
|
||||||
|
//!
|
||||||
|
//! let mut bob_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
||||||
|
//! let mut bob_ct: [u8; MyKem::CT_LEN] = [0; MyKem::CT_LEN];
|
||||||
|
//! MyKem::encaps(bob_shk.secret_mut(), &mut bob_ct, &mut alice_pk)?;
|
||||||
|
//!
|
||||||
|
//! let mut alice_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
||||||
|
//! MyKem::decaps(alice_shk.secret_mut(), alice_sk.secret_mut(), &mut bob_ct)?;
|
||||||
|
//!
|
||||||
|
//! # assert_eq!(alice_shk.secret(), bob_shk.secret());
|
||||||
|
//! # Ok::<(), anyhow::Error>(())
|
||||||
|
//!```
|
||||||
|
//!
|
||||||
|
//! Implementing the [Kem]-trait for a KEM is easy. Mostly, you must format the KEM's
|
||||||
|
//! keys, and ciphertext as `u8` slices. Below, we provide an example for how the trait can
|
||||||
|
//! be implemented using a **HORRIBLY INSECURE** DummyKem that only uses static values for keys
|
||||||
|
//! and ciphertexts as an example.
|
||||||
|
//!```rust
|
||||||
|
//!# use rosenpass_cipher_traits::Kem;
|
||||||
|
//!
|
||||||
|
//! struct DummyKem {}
|
||||||
|
//! impl Kem for DummyKem {
|
||||||
|
//!
|
||||||
|
//! // For this DummyKem, using String for errors is sufficient.
|
||||||
|
//! type Error = String;
|
||||||
|
//!
|
||||||
|
//! // For this DummyKem, we will use a single `u8` for everything
|
||||||
|
//! const SK_LEN: usize = 1;
|
||||||
|
//! const PK_LEN: usize = 1;
|
||||||
|
//! const CT_LEN: usize = 1;
|
||||||
|
//! const SHK_LEN: usize = 1;
|
||||||
|
//!
|
||||||
|
//! fn keygen(sk: &mut [u8], pk: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
|
//! if sk.len() != Self::SK_LEN {
|
||||||
|
//! return Err("sk does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if pk.len() != Self::PK_LEN {
|
||||||
|
//! return Err("pk does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! sk[0] = 42;
|
||||||
|
//! pk[0] = 21;
|
||||||
|
//! Ok(())
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn encaps(shk: &mut [u8], ct: &mut [u8], pk: &[u8]) -> Result<(), Self::Error> {
|
||||||
|
//! if pk.len() != Self::PK_LEN {
|
||||||
|
//! return Err("pk does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if ct.len() != Self::CT_LEN {
|
||||||
|
//! return Err("ct does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if shk.len() != Self::SHK_LEN {
|
||||||
|
//! return Err("shk does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if pk[0] != 21 {
|
||||||
|
//! return Err("Invalid public key!".to_string());
|
||||||
|
//! }
|
||||||
|
//! ct[0] = 7;
|
||||||
|
//! shk[0] = 17;
|
||||||
|
//! Ok(())
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! fn decaps(shk: &mut [u8], sk: &[u8], ct: &[u8]) -> Result<(), Self::Error> {
|
||||||
|
//! if sk.len() != Self::SK_LEN {
|
||||||
|
//! return Err("sk does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if ct.len() != Self::CT_LEN {
|
||||||
|
//! return Err("ct does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if shk.len() != Self::SHK_LEN {
|
||||||
|
//! return Err("shk does not have the correct length!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if sk[0] != 42 {
|
||||||
|
//! return Err("Invalid public key!".to_string());
|
||||||
|
//! }
|
||||||
|
//! if ct[0] != 7 {
|
||||||
|
//! return Err("Invalid ciphertext!".to_string());
|
||||||
|
//! }
|
||||||
|
//! shk[0] = 17;
|
||||||
|
//! Ok(())
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! # use rosenpass_secret_memory::{secret_policy_use_only_malloc_secrets, Secret};
|
||||||
|
//! #
|
||||||
|
//! # type MyKem = DummyKem;
|
||||||
|
//! # secret_policy_use_only_malloc_secrets();
|
||||||
|
//! # let mut alice_sk: Secret<{ MyKem::SK_LEN }> = Secret::zero();
|
||||||
|
//! # let mut alice_pk: [u8; MyKem::PK_LEN] = [0; MyKem::PK_LEN];
|
||||||
|
//! # MyKem::keygen(alice_sk.secret_mut(), &mut alice_pk)?;
|
||||||
|
//!
|
||||||
|
//! # let mut bob_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
||||||
|
//! # let mut bob_ct: [u8; MyKem::CT_LEN] = [0; MyKem::CT_LEN];
|
||||||
|
//! # MyKem::encaps(bob_shk.secret_mut(), &mut bob_ct, &mut alice_pk)?;
|
||||||
|
//! #
|
||||||
|
//! # let mut alice_shk: Secret<{ MyKem::SHK_LEN }> = Secret::zero();
|
||||||
|
//! # MyKem::decaps(alice_shk.secret_mut(), alice_sk.secret_mut(), &mut bob_ct)?;
|
||||||
|
//! #
|
||||||
|
//! # assert_eq!(alice_shk.secret(), bob_shk.secret());
|
||||||
|
//! #
|
||||||
|
//! # Ok::<(), String>(())
|
||||||
|
//!```
|
||||||
|
//!
|
||||||
|
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Key Encapsulation Mechanism
|
||||||
|
///
|
||||||
|
/// The KEM interface defines three operations: Key generation, key encapsulation and key
|
||||||
|
/// decapsulation.
|
||||||
|
pub trait Kem<const SK_LEN: usize, const PK_LEN: usize, const CT_LEN: usize, const SHK_LEN: usize> {
|
||||||
|
const SK_LEN: usize = SK_LEN;
|
||||||
|
const PK_LEN: usize = PK_LEN;
|
||||||
|
const CT_LEN: usize = CT_LEN;
|
||||||
|
const SHK_LEN: usize = SHK_LEN;
|
||||||
|
|
||||||
|
/// Generate a keypair consisting of secret key (`sk`) and public key (`pk`)
|
||||||
|
///
|
||||||
|
/// `keygen() -> sk, pk`
|
||||||
|
fn keygen(sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// From a public key (`pk`), generate a shared key (`shk`, for local use)
|
||||||
|
/// and a cipher text (`ct`, to be sent to the owner of the `pk`).
|
||||||
|
///
|
||||||
|
/// `encaps(pk) -> shk, ct`
|
||||||
|
fn encaps(
|
||||||
|
shk: &mut [u8; SHK_LEN],
|
||||||
|
ct: &mut [u8; CT_LEN],
|
||||||
|
pk: &[u8; PK_LEN],
|
||||||
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// From a secret key (`sk`) and a cipher text (`ct`) derive a shared key
|
||||||
|
/// (`shk`)
|
||||||
|
///
|
||||||
|
/// `decaps(sk, ct) -> shk`
|
||||||
|
fn decaps(shk: &mut [u8; SHK_LEN], sk: &[u8; SK_LEN], ct: &[u8; CT_LEN]) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("invalid argument")]
|
||||||
|
InvalidArgument,
|
||||||
|
#[error("internal error")]
|
||||||
|
InternalError,
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ extern crate rosenpass;
|
|||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass::protocol::CryptoServer;
|
use rosenpass::protocol::CryptoServer;
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_secret_memory::policy::*;
|
use rosenpass_secret_memory::policy::*;
|
||||||
use rosenpass_secret_memory::{PublicBox, Secret};
|
use rosenpass_secret_memory::{PublicBox, Secret};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::EphemeralKem;
|
use rosenpass_ciphers::kem::EphemeralKem;
|
||||||
|
|
||||||
#[derive(arbitrary::Arbitrary, Debug)]
|
#[derive(arbitrary::Arbitrary, Debug)]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ extern crate rosenpass;
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
|
|
||||||
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
|
fuzz_target!(|input: [u8; StaticKem::PK_LEN]| {
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ macro_rules! oqs_kem {
|
|||||||
($name:ident) => { ::paste::paste!{
|
($name:ident) => { ::paste::paste!{
|
||||||
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
||||||
mod [< $name:snake >] {
|
mod [< $name:snake >] {
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem;
|
||||||
use rosenpass_util::result::Guaranteed;
|
|
||||||
|
|
||||||
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
#[doc = "Bindings for ::oqs_sys::kem::" [<"OQS_KEM" _ $name:snake>] "_*"]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
@@ -39,6 +38,11 @@ macro_rules! oqs_kem {
|
|||||||
#[doc = "```"]
|
#[doc = "```"]
|
||||||
pub enum [< $name:camel >] {}
|
pub enum [< $name:camel >] {}
|
||||||
|
|
||||||
|
pub const SK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_secret_key >] as usize;
|
||||||
|
pub const PK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_public_key >] as usize;
|
||||||
|
pub const CT_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_ciphertext >] as usize;
|
||||||
|
pub const SHK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_shared_secret >] as usize;
|
||||||
|
|
||||||
/// # Panic & Safety
|
/// # Panic & Safety
|
||||||
///
|
///
|
||||||
/// This Trait impl calls unsafe [oqs_sys] functions, that write to byte
|
/// This Trait impl calls unsafe [oqs_sys] functions, that write to byte
|
||||||
@@ -51,17 +55,8 @@ macro_rules! oqs_kem {
|
|||||||
/// to only check that the buffers are big enough, allowing them to be even
|
/// to only check that the buffers are big enough, allowing them to be even
|
||||||
/// bigger. However, from a correctness point of view it does not make sense to
|
/// bigger. However, from a correctness point of view it does not make sense to
|
||||||
/// allow bigger buffers.
|
/// allow bigger buffers.
|
||||||
impl Kem for [< $name:camel >] {
|
impl kem::Kem<SK_LEN, PK_LEN, CT_LEN, SHK_LEN> for [< $name:camel >] {
|
||||||
type Error = ::std::convert::Infallible;
|
fn keygen(sk: &mut [u8; SK_LEN], pk: &mut [u8; PK_LEN]) -> Result<(), kem::Error> {
|
||||||
|
|
||||||
const SK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_secret_key >] as usize;
|
|
||||||
const PK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_public_key >] as usize;
|
|
||||||
const CT_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_ciphertext >] as usize;
|
|
||||||
const SHK_LEN: usize = ::oqs_sys::kem::[<OQS_KEM _ $name:snake _ length_shared_secret >] as usize;
|
|
||||||
|
|
||||||
fn keygen(sk: &mut [u8], pk: &mut [u8]) -> Guaranteed<()> {
|
|
||||||
assert_eq!(sk.len(), Self::SK_LEN);
|
|
||||||
assert_eq!(pk.len(), Self::PK_LEN);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ keypair >],
|
||||||
@@ -73,10 +68,7 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encaps(shk: &mut [u8], ct: &mut [u8], pk: &[u8]) -> Guaranteed<()> {
|
fn encaps(shk: &mut [u8; SHK_LEN], ct: &mut [u8; CT_LEN], pk: &[u8; PK_LEN]) -> Result<(), kem::Error> {
|
||||||
assert_eq!(shk.len(), Self::SHK_LEN);
|
|
||||||
assert_eq!(ct.len(), Self::CT_LEN);
|
|
||||||
assert_eq!(pk.len(), Self::PK_LEN);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ encaps >],
|
||||||
@@ -89,10 +81,7 @@ macro_rules! oqs_kem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decaps(shk: &mut [u8], sk: &[u8], ct: &[u8]) -> Guaranteed<()> {
|
fn decaps(shk: &mut [u8; SHK_LEN], sk: &[u8; SK_LEN], ct: &[u8; CT_LEN]) -> Result<(), kem::Error> {
|
||||||
assert_eq!(shk.len(), Self::SHK_LEN);
|
|
||||||
assert_eq!(sk.len(), Self::SK_LEN);
|
|
||||||
assert_eq!(ct.len(), Self::CT_LEN);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
oqs_call!(
|
oqs_call!(
|
||||||
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >],
|
::oqs_sys::kem::[< OQS_KEM _ $name:snake _ decaps >],
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use rosenpass::protocol::{
|
|||||||
};
|
};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
use anyhow::{bail, ensure, Context};
|
use anyhow::{bail, ensure, Context};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_secret_memory::file::StoreSecret;
|
use rosenpass_secret_memory::file::StoreSecret;
|
||||||
use rosenpass_util::file::{LoadValue, LoadValueB64, StoreValue};
|
use rosenpass_util::file::{LoadValue, LoadValueB64, StoreValue};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use std::u8;
|
|||||||
use zerocopy::{AsBytes, FromBytes, FromZeroes};
|
use zerocopy::{AsBytes, FromBytes, FromZeroes};
|
||||||
|
|
||||||
use super::RosenpassError;
|
use super::RosenpassError;
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
//! files.
|
//! files.
|
||||||
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::convert::Infallible;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@@ -21,8 +20,8 @@ use rand::Fill as Randomize;
|
|||||||
|
|
||||||
use crate::{hash_domains, msgs::*, RosenpassError};
|
use crate::{hash_domains, msgs::*, RosenpassError};
|
||||||
use memoffset::span_of;
|
use memoffset::span_of;
|
||||||
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
|
use rosenpass_cipher_traits::keyed_hash::KeyedHashInstance;
|
||||||
use rosenpass_cipher_traits::Kem;
|
|
||||||
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
||||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||||
use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
|
use rosenpass_ciphers::subtle::keyed_hash::KeyedHash;
|
||||||
@@ -3334,31 +3333,77 @@ impl HandshakeState {
|
|||||||
///
|
///
|
||||||
/// This is used to include asymmetric cryptography in the rosenpass protocol
|
/// This is used to include asymmetric cryptography in the rosenpass protocol
|
||||||
// I loathe "error: constant expression depends on a generic parameter"
|
// I loathe "error: constant expression depends on a generic parameter"
|
||||||
pub fn encaps_and_mix<T: Kem<Error = Infallible>, const SHK_LEN: usize>(
|
pub fn encaps_and_mix<
|
||||||
|
const KEM_SK_LEN: usize,
|
||||||
|
const KEM_PK_LEN: usize,
|
||||||
|
const KEM_CT_LEN: usize,
|
||||||
|
const KEM_SHK_LEN: usize,
|
||||||
|
T: Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
||||||
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ct: &mut [u8],
|
ct: &mut [u8; KEM_CT_LEN],
|
||||||
pk: &[u8],
|
pk: &[u8; KEM_PK_LEN],
|
||||||
) -> Result<&mut Self> {
|
) -> Result<&mut Self> {
|
||||||
let mut shk = Secret::<SHK_LEN>::zero();
|
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
||||||
T::encaps(shk.secret_mut(), ct, pk)?;
|
T::encaps(shk.secret_mut(), ct, pk)?;
|
||||||
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn encaps_and_mix_static(
|
||||||
|
&mut self,
|
||||||
|
ct: &mut [u8; StaticKem::CT_LEN],
|
||||||
|
pk: &[u8; StaticKem::PK_LEN],
|
||||||
|
) -> Result<&mut Self> {
|
||||||
|
self.encaps_and_mix::<{StaticKem::SK_LEN},{ StaticKem::PK_LEN}, {StaticKem::CT_LEN}, {StaticKem::SHK_LEN}, StaticKem>(ct, pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encaps_and_mix_ephemeral(
|
||||||
|
&mut self,
|
||||||
|
ct: &mut [u8; EphemeralKem::CT_LEN],
|
||||||
|
pk: &[u8; EphemeralKem::PK_LEN],
|
||||||
|
) -> Result<&mut Self> {
|
||||||
|
self.encaps_and_mix::<{EphemeralKem::SK_LEN},{ EphemeralKem::PK_LEN}, {EphemeralKem::CT_LEN}, {EphemeralKem::SHK_LEN}, EphemeralKem>(ct, pk)
|
||||||
|
}
|
||||||
|
|
||||||
/// Decapsulation (decryption) counterpart to [Self::encaps_and_mix].
|
/// Decapsulation (decryption) counterpart to [Self::encaps_and_mix].
|
||||||
///
|
///
|
||||||
/// Makes sure that the same values are mixed into the chaining that where mixed in on the
|
/// Makes sure that the same values are mixed into the chaining that where mixed in on the
|
||||||
/// sender side.
|
/// sender side.
|
||||||
pub fn decaps_and_mix<T: Kem<Error = Infallible>, const SHK_LEN: usize>(
|
pub fn decaps_and_mix<
|
||||||
|
const KEM_SK_LEN: usize,
|
||||||
|
const KEM_PK_LEN: usize,
|
||||||
|
const KEM_CT_LEN: usize,
|
||||||
|
const KEM_SHK_LEN: usize,
|
||||||
|
T: Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
||||||
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
sk: &[u8],
|
sk: &[u8; KEM_SK_LEN],
|
||||||
pk: &[u8],
|
pk: &[u8; KEM_PK_LEN],
|
||||||
ct: &[u8],
|
ct: &[u8; KEM_CT_LEN],
|
||||||
) -> Result<&mut Self> {
|
) -> Result<&mut Self> {
|
||||||
let mut shk = Secret::<SHK_LEN>::zero();
|
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
||||||
T::decaps(shk.secret_mut(), sk, ct)?;
|
T::decaps(shk.secret_mut(), sk, ct)?;
|
||||||
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn decaps_and_mix_static(
|
||||||
|
&mut self,
|
||||||
|
sk: &[u8; StaticKem::SK_LEN],
|
||||||
|
pk: &[u8; StaticKem::PK_LEN],
|
||||||
|
ct: &[u8; StaticKem::CT_LEN],
|
||||||
|
) -> Result<&mut Self> {
|
||||||
|
self.decaps_and_mix::<{StaticKem::SK_LEN},{ StaticKem::PK_LEN}, {StaticKem::CT_LEN}, {StaticKem::SHK_LEN}, StaticKem>(sk, pk, ct)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decaps_and_mix_ephemeral(
|
||||||
|
&mut self,
|
||||||
|
sk: &[u8; EphemeralKem::SK_LEN],
|
||||||
|
pk: &[u8; EphemeralKem::PK_LEN],
|
||||||
|
ct: &[u8; EphemeralKem::CT_LEN],
|
||||||
|
) -> Result<&mut Self> {
|
||||||
|
self.decaps_and_mix::<{EphemeralKem::SK_LEN},{ EphemeralKem::PK_LEN}, {EphemeralKem::CT_LEN}, {EphemeralKem::SHK_LEN}, EphemeralKem>(sk, pk, ct)
|
||||||
|
}
|
||||||
|
|
||||||
/// Store the chaining key inside a cookie value called a "biscuit".
|
/// Store the chaining key inside a cookie value called a "biscuit".
|
||||||
///
|
///
|
||||||
/// This biscuit can be transmitted to the other party and must be returned
|
/// This biscuit can be transmitted to the other party and must be returned
|
||||||
@@ -3547,10 +3592,7 @@ impl CryptoServer {
|
|||||||
|
|
||||||
// IHI5
|
// IHI5
|
||||||
hs.core
|
hs.core
|
||||||
.encaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
.encaps_and_mix_static(&mut ih.sctr, peer.get(self).spkt.deref())?;
|
||||||
ih.sctr.as_mut_slice(),
|
|
||||||
peer.get(self).spkt.deref(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// IHI6
|
// IHI6
|
||||||
hs.core.encrypt_and_mix(
|
hs.core.encrypt_and_mix(
|
||||||
@@ -3593,11 +3635,7 @@ impl CryptoServer {
|
|||||||
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
||||||
|
|
||||||
// IHR5
|
// IHR5
|
||||||
core.decaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
core.decaps_and_mix_static(self.sskm.secret(), self.spkm.deref(), &ih.sctr)?;
|
||||||
self.sskm.secret(),
|
|
||||||
self.spkm.deref(),
|
|
||||||
&ih.sctr,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// IHR6
|
// IHR6
|
||||||
let peer = {
|
let peer = {
|
||||||
@@ -3623,13 +3661,10 @@ impl CryptoServer {
|
|||||||
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
||||||
|
|
||||||
// RHR4
|
// RHR4
|
||||||
core.encaps_and_mix::<EphemeralKem, { EphemeralKem::SHK_LEN }>(&mut rh.ecti, &ih.epki)?;
|
core.encaps_and_mix_ephemeral(&mut rh.ecti, &ih.epki)?;
|
||||||
|
|
||||||
// RHR5
|
// RHR5
|
||||||
core.encaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
core.encaps_and_mix_static(&mut rh.scti, peer.get(self).spkt.deref())?;
|
||||||
&mut rh.scti,
|
|
||||||
peer.get(self).spkt.deref(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// RHR6
|
// RHR6
|
||||||
core.store_biscuit(self, peer, &mut rh.biscuit)?;
|
core.store_biscuit(self, peer, &mut rh.biscuit)?;
|
||||||
@@ -3689,18 +3724,10 @@ impl CryptoServer {
|
|||||||
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
||||||
|
|
||||||
// RHI4
|
// RHI4
|
||||||
core.decaps_and_mix::<EphemeralKem, { EphemeralKem::SHK_LEN }>(
|
core.decaps_and_mix_ephemeral(hs!().eski.secret(), hs!().epki.deref(), &rh.ecti)?;
|
||||||
hs!().eski.secret(),
|
|
||||||
hs!().epki.deref(),
|
|
||||||
&rh.ecti,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// RHI5
|
// RHI5
|
||||||
core.decaps_and_mix::<StaticKem, { StaticKem::SHK_LEN }>(
|
core.decaps_and_mix_static(self.sskm.secret(), self.spkm.deref(), &rh.scti)?;
|
||||||
self.sskm.secret(),
|
|
||||||
self.spkm.deref(),
|
|
||||||
&rh.scti,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// RHI6
|
// RHI6
|
||||||
core.mix(&rh.biscuit)?;
|
core.mix(&rh.biscuit)?;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use rosenpass::{
|
|||||||
app_server::{AppServer, AppServerTest, MAX_B64_KEY_SIZE},
|
app_server::{AppServer, AppServerTest, MAX_B64_KEY_SIZE},
|
||||||
protocol::{SPk, SSk, SymKey},
|
protocol::{SPk, SSk, SymKey},
|
||||||
};
|
};
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_util::{file::LoadValueB64, functional::run, mem::DiscardResultExt, result::OkExt};
|
use rosenpass_util::{file::LoadValueB64, functional::run, mem::DiscardResultExt, result::OkExt};
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::{
|
|||||||
ops::DerefMut,
|
ops::DerefMut,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_util::result::OkExt;
|
use rosenpass_util::result::OkExt;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use rosenpass_util::file::{LoadValueB64, StoreValue, StoreValueB64};
|
|||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
use rosenpass::protocol::{SPk, SSk};
|
use rosenpass::protocol::{SPk, SSk};
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::kem::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_secret_memory::{file::StoreSecret as _, Public, Secret};
|
use rosenpass_secret_memory::{file::StoreSecret as _, Public, Secret};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user