libcrux_curve25519/
lib.rs1#![no_std]
2
3pub use libcrux_hacl_rs::curve25519_51 as hacl;
4
5mod impl_hacl;
6
7pub mod ecdh_api;
8
9pub use impl_hacl::{ecdh, secret_to_public};
10use libcrux_secrets::{DeclassifyRef, DeclassifyRefMut, U8};
11
12pub const DK_LEN: usize = 32;
14
15pub const EK_LEN: usize = 32;
17
18pub const SS_LEN: usize = 32;
20
21pub struct Error;
23
24#[allow(dead_code)]
27trait Curve25519 {
28 fn secret_to_public(pk: &mut [u8; EK_LEN], sk: &[u8; DK_LEN]);
30
31 fn ecdh(out: &mut [u8; SS_LEN], pk: &[u8; EK_LEN], sk: &[u8; DK_LEN]) -> Result<(), Error>;
34}
35
36pub struct X25519;
37
38impl libcrux_traits::kem::arrayref::Kem<DK_LEN, EK_LEN, EK_LEN, SS_LEN, DK_LEN, DK_LEN> for X25519 {
39 fn keygen(
40 ek: &mut [u8; DK_LEN],
41 dk: &mut [U8; EK_LEN],
42 rand: &[U8; DK_LEN],
43 ) -> Result<(), libcrux_traits::kem::arrayref::KeyGenError> {
44 dk.copy_from_slice(rand);
45 clamp(dk.declassify_ref_mut());
46 secret_to_public(ek, dk.declassify_ref());
47 Ok(())
48 }
49
50 fn encaps(
51 ct: &mut [u8; EK_LEN],
52 ss: &mut [U8; SS_LEN],
53 ek: &[u8; EK_LEN],
54 rand: &[U8; DK_LEN],
55 ) -> Result<(), libcrux_traits::kem::arrayref::EncapsError> {
56 let mut eph_dk = *rand;
57 clamp(eph_dk.declassify_ref_mut());
58 secret_to_public(ct, eph_dk.declassify_ref());
59
60 ecdh(ss.declassify_ref_mut(), ek, eph_dk.declassify_ref())
61 .map_err(|_| libcrux_traits::kem::arrayref::EncapsError::Unknown)
62 }
63
64 fn decaps(
65 ss: &mut [U8; SS_LEN],
66 ct: &[u8; DK_LEN],
67 dk: &[U8; EK_LEN],
68 ) -> Result<(), libcrux_traits::kem::arrayref::DecapsError> {
69 ecdh(ss.declassify_ref_mut(), ct, dk.declassify_ref())
70 .map_err(|_| libcrux_traits::kem::arrayref::DecapsError::Unknown)
71 }
72}
73
74libcrux_traits::kem::slice::impl_trait!(X25519 => EK_LEN, DK_LEN, EK_LEN, EK_LEN, DK_LEN, DK_LEN);
75
76fn clamp(scalar: &mut [u8; DK_LEN]) {
78 scalar[0] &= 248u8;
80 scalar[31] &= 127u8;
81 scalar[31] |= 64u8;
82}