libcrux_curve25519/
lib.rs

1#![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
12/// The length of Curve25519 secret keys.
13pub const DK_LEN: usize = 32;
14
15/// The length of Curve25519 public keys.
16pub const EK_LEN: usize = 32;
17
18/// The length of Curve25519 shared keys.
19pub const SS_LEN: usize = 32;
20
21/// Indicates that an error occurred
22pub struct Error;
23
24/// This trait is implemented by the backing implementations.
25/// Only used for ensuring implementations follow the same interface, not really consumed.
26#[allow(dead_code)]
27trait Curve25519 {
28    /// Computes a public key from a secret key.
29    fn secret_to_public(pk: &mut [u8; EK_LEN], sk: &[u8; DK_LEN]);
30
31    /// Computes the scalar multiplication between the provided public and secret keys. Returns an
32    /// error if the result is 0.
33    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
76/// Clamp a scalar.
77fn clamp(scalar: &mut [u8; DK_LEN]) {
78    // We clamp the key already to make sure it can't be misused.
79    scalar[0] &= 248u8;
80    scalar[31] &= 127u8;
81    scalar[31] |= 64u8;
82}