1use core::fmt::Debug;
18use core::marker::PhantomData;
19use core::ops::Add;
20
21use derive_where::derive_where;
22use digest::Output;
23use digest::block_api::{CoreProxy, SmallBlockSizeUser};
24use generic_array::typenum::{Cmp, IsLess, Le, NonZero, Sum, U256};
25use generic_array::{ArrayLength, GenericArray};
26use hybrid_array::ArraySize;
27use ml_kem::kem::{
28 Ciphertext as MlKemCiphertext, Decapsulate, Encapsulate, Kem as MlKemTrait, KeyExport, KeyInit,
29 KeySizeUser, TryKeyInit,
30};
31use rand::{CryptoRng, Rng};
32use subtle::{ConstantTimeEq, CtOption};
33
34use super::shared::{self, Ke1Message, Ke1State, NonceLen};
35use super::{
36 Deserialize, GenerateKe1Result, GenerateKe2Result, GenerateKe3Result, KeyExchange, Serialize,
37 SerializedContext, SerializedCredentialRequest, SerializedCredentialResponse,
38 SerializedIdentifiers,
39};
40use crate::ciphersuite::{CipherSuite, KeGroup};
41use crate::errors::ProtocolError;
42use crate::hash::{Hash, OutputSize, ProxyHash};
43use crate::key_exchange::group::Group;
44use crate::keypair::{PrivateKey, PublicKey};
45use crate::opaque::Identifiers;
46use crate::serialization::{ConcatExt, SliceExt};
47
48pub trait KemCoreWrapper {
51 type EncapsulationKey: Clone;
53
54 type DecapsulationKey: Clone + zeroize::ZeroizeOnDrop;
56
57 type EncapsulationKeyLen: ArrayLength + ArraySize;
59 type DecapsulationKeyLen: ArrayLength + ArraySize;
61 type CiphertextLen: ArrayLength + ArraySize;
63 type SharedSecretLen: ArrayLength + ArraySize;
65
66 fn generate<R: Rng + CryptoRng>(
68 rng: &mut R,
69 ) -> Result<(Self::DecapsulationKey, Self::EncapsulationKey), ProtocolError>;
70
71 fn serialize_encapsulation_key(
73 key: &Self::EncapsulationKey,
74 ) -> GenericArray<u8, Self::EncapsulationKeyLen>;
75
76 fn deserialize_encapsulation_key(
78 input: &mut &[u8],
79 ) -> Result<Self::EncapsulationKey, ProtocolError>;
80
81 fn serialize_decapsulation_key(
83 key: &Self::DecapsulationKey,
84 ) -> GenericArray<u8, Self::DecapsulationKeyLen>;
85
86 fn deserialize_decapsulation_key(
88 input: &mut &[u8],
89 ) -> Result<Self::DecapsulationKey, ProtocolError>;
90
91 #[allow(clippy::type_complexity)]
94 fn encapsulate<R: Rng + CryptoRng>(
95 key: &Self::EncapsulationKey,
96 rng: &mut R,
97 ) -> Result<
98 (
99 GenericArray<u8, Self::CiphertextLen>,
100 GenericArray<u8, Self::SharedSecretLen>,
101 ),
102 ProtocolError,
103 >;
104
105 fn decapsulate(
107 key: &Self::DecapsulationKey,
108 encapsulated_key: &GenericArray<u8, Self::CiphertextLen>,
109 ) -> Result<GenericArray<u8, Self::SharedSecretLen>, ProtocolError>;
110}
111
112struct RngCompat<'a, R>(&'a mut R);
115
116impl<R: Rng> rand::rand_core::TryRng for RngCompat<'_, R> {
117 type Error = core::convert::Infallible;
118
119 fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
120 Ok(self.0.next_u32())
121 }
122
123 fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
124 Ok(self.0.next_u64())
125 }
126
127 fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
128 self.0.fill_bytes(dst);
129 Ok(())
130 }
131}
132
133impl<R: Rng + CryptoRng> rand::rand_core::TryCryptoRng for RngCompat<'_, R> {}
134
135type RcEncapsulationKeyLen<K> = <<K as MlKemTrait>::EncapsulationKey as KeySizeUser>::KeySize;
136type RcDecapsulationKeyLen<K> = <<K as MlKemTrait>::DecapsulationKey as KeySizeUser>::KeySize;
137type RcCiphertextLen<K> = <K as MlKemTrait>::CiphertextSize;
138type RcSharedSecretLen<K> = <K as MlKemTrait>::SharedKeySize;
139
140impl<K> KemCoreWrapper for K
141where
142 K: MlKemTrait,
143 K::EncapsulationKey: Encapsulate<Kem = K> + KeyExport + TryKeyInit + Clone,
144 K::DecapsulationKey:
145 Decapsulate<Kem = K> + KeyExport + KeyInit + Clone + zeroize::ZeroizeOnDrop,
146 RcEncapsulationKeyLen<K>: ArrayLength + ArraySize,
147 RcDecapsulationKeyLen<K>: ArrayLength + ArraySize,
148 RcCiphertextLen<K>: ArrayLength + ArraySize,
149 RcSharedSecretLen<K>: ArrayLength + ArraySize,
150{
151 type EncapsulationKey = K::EncapsulationKey;
152 type DecapsulationKey = K::DecapsulationKey;
153 type EncapsulationKeyLen = RcEncapsulationKeyLen<K>;
154 type DecapsulationKeyLen = RcDecapsulationKeyLen<K>;
155 type CiphertextLen = RcCiphertextLen<K>;
156 type SharedSecretLen = RcSharedSecretLen<K>;
157
158 fn generate<R: Rng + CryptoRng>(
159 rng: &mut R,
160 ) -> Result<(Self::DecapsulationKey, Self::EncapsulationKey), ProtocolError> {
161 Ok(K::generate_keypair_from_rng(&mut RngCompat(rng)))
162 }
163
164 fn serialize_encapsulation_key(
165 key: &Self::EncapsulationKey,
166 ) -> GenericArray<u8, Self::EncapsulationKeyLen> {
167 GenericArray::from_slice(key.to_bytes().as_slice()).clone()
168 }
169
170 fn deserialize_encapsulation_key(
171 input: &mut &[u8],
172 ) -> Result<Self::EncapsulationKey, ProtocolError> {
173 let bytes: GenericArray<u8, RcEncapsulationKeyLen<K>> =
174 input.take_array("kem encapsulation key")?;
175 let key = ml_kem::array::Array::try_from(bytes.as_slice())
176 .map_err(|_| ProtocolError::SerializationError)?;
177 TryKeyInit::new(&key).map_err(|_| ProtocolError::SerializationError)
178 }
179
180 fn serialize_decapsulation_key(
181 key: &Self::DecapsulationKey,
182 ) -> GenericArray<u8, Self::DecapsulationKeyLen> {
183 GenericArray::from_slice(key.to_bytes().as_slice()).clone()
184 }
185
186 fn deserialize_decapsulation_key(
187 input: &mut &[u8],
188 ) -> Result<Self::DecapsulationKey, ProtocolError> {
189 let bytes: GenericArray<u8, RcDecapsulationKeyLen<K>> =
190 input.take_array("kem decapsulation key")?;
191 let seed = ml_kem::array::Array::try_from(bytes.as_slice())
192 .map_err(|_| ProtocolError::SerializationError)?;
193 Ok(KeyInit::new(&seed))
194 }
195
196 fn encapsulate<R: Rng + CryptoRng>(
197 key: &Self::EncapsulationKey,
198 rng: &mut R,
199 ) -> Result<
200 (
201 GenericArray<u8, Self::CiphertextLen>,
202 GenericArray<u8, Self::SharedSecretLen>,
203 ),
204 ProtocolError,
205 > {
206 let (ciphertext, shared) = key.encapsulate_with_rng(&mut RngCompat(rng));
207 Ok((
208 GenericArray::from_slice(ciphertext.as_slice()).clone(),
209 GenericArray::from_slice(shared.as_slice()).clone(),
210 ))
211 }
212
213 fn decapsulate(
214 key: &Self::DecapsulationKey,
215 encapsulated_key: &GenericArray<u8, Self::CiphertextLen>,
216 ) -> Result<GenericArray<u8, Self::SharedSecretLen>, ProtocolError> {
217 let ciphertext = MlKemCiphertext::<K>::try_from(encapsulated_key.as_slice())
218 .map_err(|_| ProtocolError::SerializationError)?;
219 let shared = key.decapsulate(&ciphertext);
220 Ok(GenericArray::from_slice(shared.as_slice()).clone())
221 }
222}
223#[derive(Clone, Debug)]
226pub struct TripleDhKem<G, H, K>(PhantomData<(G, H, K)>);
227
228#[cfg_attr(
230 feature = "serde",
231 derive(serde::Deserialize, serde::Serialize),
232 serde(bound(
233 deserialize = "Ke1State<G>: serde::Deserialize<'de>, K::DecapsulationKey: \
234 serde::Deserialize<'de>",
235 serialize = "Ke1State<G>: serde::Serialize, K::DecapsulationKey: serde::Serialize",
236 ))
237)]
238#[derive_where(Clone, ZeroizeOnDrop)]
239#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; Ke1State<G>, K::DecapsulationKey)]
240pub struct KemKe1State<G: Group, K: KemCoreWrapper> {
241 dh_state: Ke1State<G>,
242 kem_decapsulation_key: K::DecapsulationKey,
243}
244
245#[cfg_attr(
248 feature = "serde",
249 derive(serde::Deserialize, serde::Serialize),
250 serde(bound(
251 deserialize = "Ke1Message<G>: serde::Deserialize<'de>",
252 serialize = "Ke1Message<G>: serde::Serialize",
253 ))
254)]
255#[derive_where(Clone, ZeroizeOnDrop)]
256#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; Ke1Message<G>)]
257pub struct KemKe1Message<G: Group, K: KemCoreWrapper> {
258 dh_message: Ke1Message<G>,
259 kem_encapsulation_key: GenericArray<u8, K::EncapsulationKeyLen>,
260}
261
262#[cfg_attr(
265 feature = "serde",
266 derive(serde::Deserialize, serde::Serialize),
267 serde(bound = "")
268)]
269#[derive_where(Clone, ZeroizeOnDrop)]
270#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
271pub struct KemKe2State<K: KemCoreWrapper, H: Hash>
272where
273 H::Core: ProxyHash,
274 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
275 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
276 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
277 OutputSize<H>: ArrayLength,
278{
279 base_state: super::tripledh::Ke2State<H>,
280 kem_encapsulation_key: GenericArray<u8, K::EncapsulationKeyLen>,
281 server_kem_ciphertext: GenericArray<u8, K::CiphertextLen>,
282}
283
284#[derive_where(Clone, ZeroizeOnDrop)]
287pub struct KemKe2Builder<G: Group, H: Hash, K: KemCoreWrapper>
288where
289 H::Core: ProxyHash,
290 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
291 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
292 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
293 OutputSize<H>: ArrayLength,
294{
295 server_nonce: GenericArray<u8, NonceLen>,
296 transcript_hasher: H,
297 #[derive_where(skip(Zeroize))]
298 client_e_pk: PublicKey<G>,
299 #[derive_where(skip(Zeroize))]
300 server_e_pk: PublicKey<G>,
301 shared_secret_1: GenericArray<u8, G::PkLen>,
302 shared_secret_3: GenericArray<u8, G::PkLen>,
303 #[derive_where(skip(Zeroize))]
304 kem_encapsulation_key: GenericArray<u8, K::EncapsulationKeyLen>,
305 kem_ciphertext: GenericArray<u8, K::CiphertextLen>,
306 kem_shared_secret: GenericArray<u8, K::SharedSecretLen>,
307}
308
309#[cfg_attr(
311 feature = "serde",
312 derive(serde::Deserialize, serde::Serialize),
313 serde(bound(
314 deserialize = "super::tripledh::Ke2Message<G, H>: serde::Deserialize<'de>",
315 serialize = "super::tripledh::Ke2Message<G, H>: serde::Serialize",
316 ))
317)]
318#[derive_where(Clone, ZeroizeOnDrop)]
319#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; super::tripledh::Ke2Message<G, H>)]
320pub struct KemKe2Message<G: Group, H: Hash, K: KemCoreWrapper>
321where
322 H::Core: ProxyHash,
323 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
324 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
325 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
326 OutputSize<H>: ArrayLength,
327{
328 dh_message: super::tripledh::Ke2Message<G, H>,
329 kem_ciphertext: GenericArray<u8, K::CiphertextLen>,
330}
331
332pub type KemKe3Message<H> = super::tripledh::Ke3Message<H>;
334
335impl<G, H, K> KeyExchange for TripleDhKem<G, H, K>
336where
337 G: Group + 'static,
338 G::Sk: shared::DiffieHellman<G>,
339 H: Hash,
340 H::Core: ProxyHash,
341 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
342 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
343 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
344 OutputSize<H>: ArrayLength,
345 K: KemCoreWrapper,
346 NonceLen: Add<K::EncapsulationKeyLen>,
347 Sum<NonceLen, K::EncapsulationKeyLen>: ArrayLength,
348{
349 type Group = G;
350 type Hash = H;
351
352 type KE1State = KemKe1State<G, K>;
353 type KE2State<CS: CipherSuite> = KemKe2State<K, H>;
354 type KE1Message = KemKe1Message<G, K>;
355 type KE2Builder<'a, CS: CipherSuite<KeyExchange = Self>> = KemKe2Builder<G, H, K>;
356 type KE2BuilderData<'a, CS: 'static + CipherSuite> = (
357 &'a PublicKey<G>,
358 &'a GenericArray<u8, K::EncapsulationKeyLen>,
359 );
360 type KE2BuilderInput<CS: CipherSuite> = GenericArray<u8, G::PkLen>;
361 type KE2Message = KemKe2Message<G, H, K>;
362 type KE3Message = KemKe3Message<H>;
363
364 fn generate_ke1<R: Rng + CryptoRng>(
365 rng: &mut R,
366 ) -> Result<GenerateKe1Result<Self>, ProtocolError> {
367 let base = super::tripledh::TripleDh::<G, H>::generate_ke1(rng)?;
368 let (kem_secret, kem_public) = K::generate(rng)?;
369 let kem_encapsulation_key = K::serialize_encapsulation_key(&kem_public);
370
371 Ok(GenerateKe1Result {
372 state: KemKe1State {
373 dh_state: base.state,
374 kem_decapsulation_key: kem_secret,
375 },
376 message: KemKe1Message {
377 dh_message: base.message,
378 kem_encapsulation_key,
379 },
380 })
381 }
382
383 fn ke2_builder<'a, CS: CipherSuite<KeyExchange = Self>, R: Rng + CryptoRng>(
384 rng: &mut R,
385 credential_request: SerializedCredentialRequest<CS>,
386 ke1_message: Self::KE1Message,
387 credential_response: SerializedCredentialResponse<CS>,
388 client_s_pk: PublicKey<G>,
389 identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
390 context: SerializedContext<'a>,
391 ) -> Result<Self::KE2Builder<'a, CS>, ProtocolError> {
392 let shared::Ke2BuilderCommon {
393 server_nonce,
394 transcript_hasher,
395 client_e_pk,
396 server_e_pk,
397 shared_secret_1,
398 shared_secret_3,
399 } = shared::ke2_builder_common::<G, H, CS, R>(
400 rng,
401 credential_request,
402 ke1_message.dh_message.clone(),
403 credential_response,
404 client_s_pk,
405 identifiers,
406 context,
407 )?;
408
409 let mut kem_bytes_slice: &[u8] = ke1_message.kem_encapsulation_key.as_slice();
410 let encapsulation_key = K::deserialize_encapsulation_key(&mut kem_bytes_slice)?;
411 let (kem_ciphertext, kem_shared_secret) = K::encapsulate(&encapsulation_key, rng)?;
412
413 let mut transcript_hasher = transcript_hasher;
414 digest::Digest::update(
415 &mut transcript_hasher,
416 ke1_message.kem_encapsulation_key.as_slice(),
417 );
418 digest::Digest::update(&mut transcript_hasher, kem_ciphertext.as_slice());
419
420 Ok(KemKe2Builder {
421 server_nonce,
422 transcript_hasher,
423 client_e_pk,
424 server_e_pk,
425 shared_secret_1,
426 shared_secret_3,
427 kem_encapsulation_key: ke1_message.kem_encapsulation_key.clone(),
428 kem_ciphertext,
429 kem_shared_secret,
430 })
431 }
432
433 fn ke2_builder_data<'a, CS: 'static + CipherSuite<KeyExchange = Self>>(
434 builder: &'a Self::KE2Builder<'_, CS>,
435 ) -> Self::KE2BuilderData<'a, CS> {
436 (&builder.client_e_pk, &builder.kem_encapsulation_key)
437 }
438
439 fn generate_ke2_input<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
440 builder: &Self::KE2Builder<'_, CS>,
441 _: &mut R,
442 server_s_sk: &PrivateKey<G>,
443 ) -> Self::KE2BuilderInput<CS> {
444 server_s_sk.ke_diffie_hellman(&builder.client_e_pk)
445 }
446
447 fn build_ke2<CS: CipherSuite<KeyExchange = Self>>(
448 mut builder: Self::KE2Builder<'_, CS>,
449 shared_secret_2: Self::KE2BuilderInput<CS>,
450 ) -> Result<GenerateKe2Result<CS>, ProtocolError> {
451 let transcript_digest = builder.transcript_hasher.clone().finalize();
452 let derived_keys = shared::derive_keys::<H>(
453 [
454 builder.shared_secret_1.as_slice(),
455 shared_secret_2.as_slice(),
456 builder.shared_secret_3.as_slice(),
457 builder.kem_shared_secret.as_slice(),
458 ]
459 .into_iter(),
460 &transcript_digest,
461 )?;
462
463 let (mac, expected_mac) = shared::compute_ke2_macs(
464 &mut builder.transcript_hasher,
465 &derived_keys,
466 &transcript_digest,
467 )?;
468
469 Ok(GenerateKe2Result {
470 state: KemKe2State {
471 base_state: super::tripledh::Ke2State {
472 session_key: derived_keys.session_key.clone(),
473 expected_mac,
474 },
475 kem_encapsulation_key: builder.kem_encapsulation_key.clone(),
476 server_kem_ciphertext: builder.kem_ciphertext.clone(),
477 },
478 message: KemKe2Message {
479 dh_message: super::tripledh::Ke2Message {
480 server_nonce: builder.server_nonce,
481 server_e_pk: builder.server_e_pk.clone(),
482 mac,
483 },
484 kem_ciphertext: builder.kem_ciphertext.clone(),
485 },
486 #[cfg(test)]
487 handshake_secret: derived_keys.handshake_secret,
488 #[cfg(test)]
489 km2: derived_keys.km2,
490 })
491 }
492
493 fn generate_ke3<CS: CipherSuite<KeyExchange = Self>, R: CryptoRng + Rng>(
494 _rng: &mut R,
495 credential_request: SerializedCredentialRequest<CS>,
496 ke1_message: Self::KE1Message,
497 credential_response: SerializedCredentialResponse<CS>,
498 ke1_state: &Self::KE1State,
499 ke2_message: Self::KE2Message,
500 server_s_pk: PublicKey<G>,
501 client_s_sk: PrivateKey<G>,
502 identifiers: SerializedIdentifiers<'_, KeGroup<CS>>,
503 context: SerializedContext<'_>,
504 ) -> Result<GenerateKe3Result<Self>, ProtocolError> {
505 let mut transcript_hasher = shared::transcript(
506 &context,
507 &identifiers,
508 &credential_request,
509 &ke1_message.dh_message.to_iter(),
510 &credential_response,
511 ke2_message.dh_message.server_nonce,
512 &ke2_message.dh_message.server_e_pk.serialize(),
513 );
514 digest::Digest::update(
515 &mut transcript_hasher,
516 ke1_message.kem_encapsulation_key.as_slice(),
517 );
518 digest::Digest::update(
519 &mut transcript_hasher,
520 ke2_message.kem_ciphertext.as_slice(),
521 );
522
523 let shared_secret_1 = ke1_state
524 .dh_state
525 .client_e_sk
526 .ke_diffie_hellman(&ke2_message.dh_message.server_e_pk);
527 let shared_secret_2 = ke1_state
528 .dh_state
529 .client_e_sk
530 .ke_diffie_hellman(&server_s_pk);
531 let shared_secret_3 = client_s_sk.ke_diffie_hellman(&ke2_message.dh_message.server_e_pk);
532 let kem_shared_secret = K::decapsulate(
533 &ke1_state.kem_decapsulation_key,
534 &ke2_message.kem_ciphertext,
535 )?;
536
537 let (derived_keys, client_mac) = shared::finalize_ke3_transcript(
538 &mut transcript_hasher,
539 [
540 shared_secret_1.as_slice(),
541 shared_secret_2.as_slice(),
542 shared_secret_3.as_slice(),
543 kem_shared_secret.as_slice(),
544 ]
545 .into_iter(),
546 &ke2_message.dh_message.mac,
547 )?;
548
549 Ok(GenerateKe3Result {
550 session_key: derived_keys.session_key,
551 message: super::tripledh::Ke3Message { mac: client_mac },
552 #[cfg(test)]
553 handshake_secret: derived_keys.handshake_secret,
554 #[cfg(test)]
555 km3: derived_keys.km3,
556 })
557 }
558
559 fn finish_ke<CS: CipherSuite>(
560 ke2_state: &Self::KE2State<CS>,
561 ke3_message: Self::KE3Message,
562 _identifiers: Identifiers<'_>,
563 _context: SerializedContext<'_>,
564 ) -> Result<Output<Self::Hash>, ProtocolError> {
565 CtOption::new(
566 ke2_state.base_state.session_key.clone(),
567 ke2_state.base_state.expected_mac.ct_eq(&ke3_message.mac),
568 )
569 .into_option()
570 .ok_or(ProtocolError::InvalidLoginError)
571 }
572}
573
574impl<G: Group, K: KemCoreWrapper> Deserialize for KemKe1State<G, K> {
577 fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
578 Ok(Self {
579 dh_state: Ke1State::<G>::deserialize_take(input)?,
580 kem_decapsulation_key: K::deserialize_decapsulation_key(input)?,
581 })
582 }
583}
584
585impl<G: Group, K: KemCoreWrapper> Serialize for KemKe1State<G, K>
586where
587 Ke1State<G>: Serialize,
588 <Ke1State<G> as Serialize>::Len: Add<K::DecapsulationKeyLen>,
589 Sum<<Ke1State<G> as Serialize>::Len, K::DecapsulationKeyLen>: ArrayLength,
590{
591 type Len = Sum<<Ke1State<G> as Serialize>::Len, K::DecapsulationKeyLen>;
592
593 fn serialize(&self) -> GenericArray<u8, Self::Len> {
594 self.dh_state
595 .serialize()
596 .cat(K::serialize_decapsulation_key(&self.kem_decapsulation_key))
597 }
598}
599
600impl<G: Group, K: KemCoreWrapper> Deserialize for KemKe1Message<G, K> {
601 fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
602 Ok(Self {
603 dh_message: Ke1Message::<G>::deserialize_take(input)?,
604 kem_encapsulation_key: input.take_array("kem encapsulation key")?,
605 })
606 }
607}
608
609impl<G: Group, K: KemCoreWrapper> Serialize for KemKe1Message<G, K>
610where
611 Ke1Message<G>: Serialize,
612 <Ke1Message<G> as Serialize>::Len: Add<K::EncapsulationKeyLen>,
613 Sum<<Ke1Message<G> as Serialize>::Len, K::EncapsulationKeyLen>: ArrayLength,
614{
615 type Len = Sum<<Ke1Message<G> as Serialize>::Len, K::EncapsulationKeyLen>;
616
617 fn serialize(&self) -> GenericArray<u8, Self::Len> {
618 self.dh_message
619 .serialize()
620 .cat(self.kem_encapsulation_key.clone())
621 }
622}
623
624impl<K: KemCoreWrapper, H: Hash> Deserialize for KemKe2State<K, H>
625where
626 H::Core: ProxyHash,
627 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
628 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
629 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
630 OutputSize<H>: ArrayLength,
631{
632 fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
633 Ok(Self {
634 base_state: super::tripledh::Ke2State::<H>::deserialize_take(input)?,
635 kem_encapsulation_key: input.take_array("kem encapsulation key")?,
636 server_kem_ciphertext: input.take_array("kem ciphertext")?,
637 })
638 }
639}
640
641impl<K: KemCoreWrapper, H: Hash> Serialize for KemKe2State<K, H>
642where
643 H::Core: ProxyHash,
644 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
645 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
646 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
647 OutputSize<H>: ArrayLength,
648 super::tripledh::Ke2State<H>: Serialize,
649 <super::tripledh::Ke2State<H> as Serialize>::Len: Add<K::EncapsulationKeyLen>,
650 Sum<<super::tripledh::Ke2State<H> as Serialize>::Len, K::EncapsulationKeyLen>:
651 ArrayLength + Add<K::CiphertextLen>,
652 Sum<
653 Sum<<super::tripledh::Ke2State<H> as Serialize>::Len, K::EncapsulationKeyLen>,
654 K::CiphertextLen,
655 >: ArrayLength,
656{
657 type Len = Sum<
658 Sum<<super::tripledh::Ke2State<H> as Serialize>::Len, K::EncapsulationKeyLen>,
659 K::CiphertextLen,
660 >;
661
662 fn serialize(&self) -> GenericArray<u8, Self::Len> {
663 self.base_state
664 .serialize()
665 .cat(self.kem_encapsulation_key.clone())
666 .cat(self.server_kem_ciphertext.clone())
667 }
668}
669
670impl<G: Group, H: Hash, K: KemCoreWrapper> Deserialize for KemKe2Message<G, H, K>
671where
672 H::Core: ProxyHash,
673 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
674 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
675 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
676 OutputSize<H>: ArrayLength,
677{
678 fn deserialize_take(input: &mut &[u8]) -> Result<Self, ProtocolError> {
679 Ok(Self {
680 dh_message: super::tripledh::Ke2Message::<G, H>::deserialize_take(input)?,
681 kem_ciphertext: input.take_array("kem ciphertext")?,
682 })
683 }
684}
685
686impl<G: Group, H: Hash, K: KemCoreWrapper> Serialize for KemKe2Message<G, H, K>
687where
688 H::Core: ProxyHash,
689 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: IsLess<U256>,
690 Le<<<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize, U256>: NonZero,
691 <<H as CoreProxy>::Core as SmallBlockSizeUser>::_BlockSize: Cmp<U256>,
692 OutputSize<H>: ArrayLength,
693 NonceLen: Add<G::PkLen>,
694 Sum<NonceLen, G::PkLen>: ArrayLength + Add<OutputSize<H>>,
695 Sum<Sum<NonceLen, G::PkLen>, OutputSize<H>>: ArrayLength,
696 super::tripledh::Ke2Message<G, H>: Serialize,
697 <super::tripledh::Ke2Message<G, H> as Serialize>::Len: Add<K::CiphertextLen>,
698 <<super::tripledh::Ke2Message<G, H> as Serialize>::Len as Add<K::CiphertextLen>>::Output:
699 ArrayLength,
700{
701 type Len = Sum<<super::tripledh::Ke2Message<G, H> as Serialize>::Len, K::CiphertextLen>;
702
703 fn serialize(&self) -> GenericArray<u8, Self::Len> {
704 self.dh_message.serialize().cat(self.kem_ciphertext.clone())
705 }
706}