1#![no_std]
9
10extern crate alloc;
11
12use alloc::{string::String, vec::Vec};
13
14mod hacl;
15
16#[derive(Debug, PartialEq, Eq)]
17pub enum LowLevelError {
18 Jasmin(String),
19 Hacl(hacl::Error),
20}
21
22#[derive(Debug, PartialEq, Eq)]
23pub enum Error {
24 InvalidPoint,
25 InvalidScalar,
26 UnknownAlgorithm,
27 KeyGenError,
28 Custom(String),
29 Wrap(LowLevelError),
30}
31
32impl From<hacl::p256::Error> for Error {
33 fn from(value: hacl::p256::Error) -> Self {
34 Error::Wrap(LowLevelError::Hacl(hacl::Error::P256(value)))
35 }
36}
37
38#[derive(Debug, PartialEq, Eq, Clone, Copy)]
40pub enum Algorithm {
41 X25519,
42 X448,
43 P256,
44 P384,
45 P521,
46}
47
48pub(crate) mod x25519;
50pub use x25519::{
51 derive as x25519_derive, generate_secret as x25519_generate_secret, key_gen as x25519_key_gen,
52 PrivateKey as X25519PrivateKey, PublicKey as X25519PublicKey,
53 SharedSecret as X25519SharedSecret,
54};
55
56pub mod curve25519 {
57 use super::hacl;
58 pub use hacl::curve25519::Error;
59}
60
61pub(crate) mod p256_internal;
63
64pub mod p256 {
65 use super::hacl;
66 pub use hacl::p256::{
67 compressed_to_coordinates, uncompressed_to_coordinates, validate_point,
68 validate_scalar_slice, Error,
69 };
70}
71
72pub use p256_internal::{
73 generate_secret as p256_generate_secret, key_gen as p256_key_gen,
74 validate_scalar as p256_validate_scalar, PrivateKey as P256PrivateKey,
75 PublicKey as P256PublicKey, SharedSecret as P256SharedSecret,
76};
77
78pub fn derive(
81 alg: Algorithm,
82 point: impl AsRef<[u8]>,
83 scalar: impl AsRef<[u8]>,
84) -> Result<Vec<u8>, Error> {
85 match alg {
86 Algorithm::X25519 => {
87 x25519::derive(&point.as_ref().try_into()?, &scalar.as_ref().try_into()?)
88 .map(|r| r.0.into())
89 }
90 Algorithm::P256 => {
91 let point = p256_internal::prepare_public_key(point.as_ref())?;
92 let scalar = hacl::p256::validate_scalar_slice(scalar.as_ref())
93 .map_err(|_| Error::InvalidScalar)?;
94
95 p256_internal::derive(&point, &scalar).map(|r| r.0.into())
96 }
97 _ => Err(Error::UnknownAlgorithm),
98 }
99}
100
101pub fn p256_derive(
102 point: &p256_internal::PublicKey,
103 scalar: &p256_internal::PrivateKey,
104) -> Result<p256_internal::SharedSecret, Error> {
105 p256_internal::validate_point(point)?;
106 p256_internal::validate_scalar(scalar)?;
107
108 p256_internal::derive(point, scalar)
109}
110
111pub fn secret_to_public(alg: Algorithm, scalar: impl AsRef<[u8]>) -> Result<Vec<u8>, Error> {
113 match alg {
114 Algorithm::X25519 => {
115 x25519::secret_to_public(&scalar.as_ref().try_into()?).map(|r| r.0.into())
116 }
117 Algorithm::P256 => {
118 p256_internal::secret_to_public(&scalar.as_ref().try_into()?).map(|r| r.0.into())
119 }
120 _ => Err(Error::UnknownAlgorithm),
121 }
122}
123
124pub fn validate_scalar(alg: Algorithm, s: impl AsRef<[u8]>) -> Result<(), Error> {
126 match alg {
127 Algorithm::X25519 => {
128 if s.as_ref().iter().all(|&b| b == 0) {
129 Err(Error::InvalidScalar)
130 } else {
131 Ok(())
132 }
133 }
134 Algorithm::P256 => p256_internal::validate_scalar(&s.as_ref().try_into()?),
135 _ => Err(Error::UnknownAlgorithm),
136 }
137}
138
139use rand::{CryptoRng, Rng};
140
141pub fn generate_secret(alg: Algorithm, rng: &mut (impl CryptoRng + Rng)) -> Result<Vec<u8>, Error> {
146 match alg {
147 Algorithm::X25519 => x25519::generate_secret(rng).map(|k| k.0.to_vec()),
148 Algorithm::P256 => p256_internal::generate_secret(rng).map(|k| k.0.to_vec()),
149 _ => Err(Error::UnknownAlgorithm),
150 }
151}
152
153pub fn key_gen(
157 alg: Algorithm,
158 rng: &mut (impl CryptoRng + Rng),
159) -> Result<(Vec<u8>, Vec<u8>), Error> {
160 let sk = generate_secret(alg, rng)?;
161 let pk = secret_to_public(alg, &sk)?;
162 Ok((sk, pk))
163}