1use crate::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 {
49 use rand::{CryptoRng, Rng};
50
51 use super::Error;
52
53 pub struct PrivateKey(pub [u8; 32]);
54 pub struct PublicKey(pub [u8; 32]);
55
56 impl From<&[u8; 32]> for PublicKey {
57 fn from(value: &[u8; 32]) -> Self {
58 Self(value.clone())
59 }
60 }
61
62 impl TryFrom<&[u8]> for PublicKey {
63 type Error = Error;
64
65 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
66 Ok(Self(value.try_into().map_err(|_| Error::InvalidPoint)?))
67 }
68 }
69
70 impl TryFrom<crate::kem::PublicKey> for PublicKey {
71 type Error = Error;
72
73 fn try_from(value: crate::kem::PublicKey) -> Result<Self, Self::Error> {
74 if let crate::kem::PublicKey::X25519(k) = value {
75 Ok(k)
76 } else {
77 Err(Error::InvalidPoint)
78 }
79 }
80 }
81
82 impl From<&[u8; 32]> for PrivateKey {
83 fn from(value: &[u8; 32]) -> Self {
84 Self(value.clone())
85 }
86 }
87
88 impl TryFrom<&[u8]> for PrivateKey {
89 type Error = Error;
90
91 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
92 Ok(Self(value.try_into().map_err(|_| Error::InvalidScalar)?))
93 }
94 }
95
96 impl TryFrom<crate::kem::PrivateKey> for PrivateKey {
97 type Error = Error;
98
99 fn try_from(value: crate::kem::PrivateKey) -> Result<Self, Self::Error> {
100 if let crate::kem::PrivateKey::X25519(k) = value {
101 Ok(k)
102 } else {
103 Err(Error::InvalidScalar)
104 }
105 }
106 }
107
108 impl AsRef<[u8]> for PrivateKey {
109 fn as_ref(&self) -> &[u8] {
110 &self.0
111 }
112 }
113
114 impl AsRef<[u8]> for PublicKey {
115 fn as_ref(&self) -> &[u8] {
116 &self.0
117 }
118 }
119
120 impl AsRef<[u8; 32]> for PrivateKey {
121 fn as_ref(&self) -> &[u8; 32] {
122 &self.0
123 }
124 }
125
126 impl AsRef<[u8; 32]> for PublicKey {
127 fn as_ref(&self) -> &[u8; 32] {
128 &self.0
129 }
130 }
131
132 #[cfg(all(bmi2, adx, target_arch = "x86_64"))]
133 pub(crate) fn derive(p: &PublicKey, s: &PrivateKey) -> Result<PublicKey, Error> {
134 use crate::hacl::curve25519;
135 use libcrux_platform::x25519_support;
136 if x25519_support() {
140 curve25519::vale::ecdh(s, p)
141 .map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))
142 .map(|p| PublicKey(p))
143 } else {
147 curve25519::ecdh(s, p)
148 .map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))
149 .map(|p| PublicKey(p))
150 }
154 }
155
156 #[cfg(any(
157 all(target_arch = "x86_64", any(not(bmi2), not(adx))),
158 target_arch = "x86"
159 ))]
160 pub(crate) fn derive(p: &PublicKey, s: &PrivateKey) -> Result<PublicKey, Error> {
161 use crate::hacl::curve25519;
162 curve25519::ecdh(s, p)
166 .map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))
167 .map(|p| PublicKey(p))
168 }
172
173 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
174 pub(crate) fn derive(p: &PublicKey, s: &PrivateKey) -> Result<PublicKey, Error> {
175 use crate::hacl::curve25519;
177
178 curve25519::ecdh(s, p)
179 .map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))
180 .map(|p| PublicKey(p))
181 }
182
183 pub(crate) fn secret_to_public(s: &PrivateKey) -> Result<PublicKey, Error> {
191 use crate::hacl::curve25519;
193
194 Ok(PublicKey(curve25519::secret_to_public(s)))
195 }
196
197 pub fn generate_secret(rng: &mut (impl CryptoRng + Rng)) -> Result<PrivateKey, Error> {
199 const LIMIT: usize = 100;
200 for _ in 0..LIMIT {
201 let mut out = [0u8; 32];
202 rng.try_fill_bytes(&mut out)
203 .map_err(|_| Error::KeyGenError)?;
204
205 if out.iter().all(|&b| b == 0) {
207 continue;
208 }
209
210 out[0] = out[0] & 248u8;
212 out[31] = out[31] & 127u8;
213 out[31] = out[31] | 64u8;
214
215 return Ok(PrivateKey(out));
216 }
217
218 Err(Error::KeyGenError)
219 }
220
221 pub fn key_gen(rng: &mut (impl CryptoRng + Rng)) -> Result<(PrivateKey, PublicKey), Error> {
223 let sk = generate_secret(rng)?;
224 let pk = secret_to_public(&sk)?;
225 Ok((sk, pk))
226 }
227}
228
229pub use x25519::generate_secret as x25519_generate_secret;
230pub use x25519::key_gen as x25519_key_gen;
231
232pub(crate) mod p256 {
233 use rand::{CryptoRng, Rng};
234
235 use crate::hacl::p256;
237
238 use super::Error;
239
240 pub struct PrivateKey(pub [u8; 32]);
241 pub struct PublicKey(pub [u8; 64]);
242
243 impl From<&[u8; 64]> for PublicKey {
244 fn from(value: &[u8; 64]) -> Self {
245 Self(value.clone())
246 }
247 }
248
249 impl TryFrom<&[u8]> for PublicKey {
250 type Error = Error;
251
252 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
253 Ok(Self(value.try_into().map_err(|_| Error::InvalidPoint)?))
254 }
255 }
256
257 impl From<&[u8; 32]> for PrivateKey {
258 fn from(value: &[u8; 32]) -> Self {
259 Self(value.clone())
260 }
261 }
262
263 impl TryFrom<&[u8]> for PrivateKey {
264 type Error = Error;
265
266 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
267 Ok(Self(value.try_into().map_err(|_| Error::InvalidScalar)?))
268 }
269 }
270
271 impl AsRef<[u8]> for PrivateKey {
272 fn as_ref(&self) -> &[u8] {
273 &self.0
274 }
275 }
276
277 impl AsRef<[u8]> for PublicKey {
278 fn as_ref(&self) -> &[u8] {
279 &self.0
280 }
281 }
282
283 impl AsRef<[u8; 32]> for PrivateKey {
284 fn as_ref(&self) -> &[u8; 32] {
285 &self.0
286 }
287 }
288
289 impl AsRef<[u8; 64]> for PublicKey {
290 fn as_ref(&self) -> &[u8; 64] {
291 &self.0
292 }
293 }
294
295 pub(super) fn derive(p: &PublicKey, s: &PrivateKey) -> Result<PublicKey, Error> {
296 p256::ecdh(s, p)
298 .map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))
299 .map(|p| PublicKey(p))
300 }
301
302 pub(super) fn secret_to_public(s: &PrivateKey) -> Result<PublicKey, Error> {
303 p256::validate_scalar(s).map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))?;
304 p256::secret_to_public(s)
305 .map_err(|e| Error::Custom(format!("HACL Error {:?}", e)))
306 .map(|p| PublicKey(p))
307 }
308
309 pub fn validate_scalar(s: &PrivateKey) -> Result<(), Error> {
310 p256::validate_scalar(s).map_err(|e| e.into())
311 }
312
313 #[allow(unused)]
314 pub fn validate_point(p: &PublicKey) -> Result<(), Error> {
315 p256::validate_point(p).map_err(|e| e.into())
316 }
317
318 pub(crate) fn prepare_public_key(public_key: &[u8]) -> Result<PublicKey, Error> {
319 if public_key.is_empty() {
320 return Err(Error::InvalidPoint);
321 }
322
323 let pk = if let Ok(pk) = p256::uncompressed_to_coordinates(public_key) {
325 pk
326 } else {
327 if public_key.len() == 33 {
329 p256::compressed_to_coordinates(public_key).map_err(|_| Error::InvalidPoint)?
330 } else {
331 public_key.try_into().map_err(|_| Error::InvalidPoint)?
333 }
334 };
335 let pk = PublicKey(pk);
336
337 p256::validate_point(&pk)
338 .map(|()| pk)
339 .map_err(|_| Error::InvalidPoint)
340 }
341
342 pub fn generate_secret(rng: &mut (impl CryptoRng + Rng)) -> Result<PrivateKey, Error> {
344 const LIMIT: usize = 100;
345 for _ in 0..LIMIT {
346 let mut out = [0u8; 32];
347 rng.try_fill_bytes(&mut out)
348 .map_err(|_| Error::KeyGenError)?;
349
350 let out = PrivateKey(out);
351 if validate_scalar(&out).is_ok() {
352 return Ok(out);
353 }
354 }
355 Err(Error::KeyGenError)
356 }
357
358 pub fn key_gen(rng: &mut (impl CryptoRng + Rng)) -> Result<(PrivateKey, PublicKey), Error> {
360 let sk = generate_secret(rng)?;
361 let pk = secret_to_public(&sk)?;
362 Ok((sk, pk))
363 }
364}
365
366pub use p256::generate_secret as p256_generate_secret;
367pub use p256::key_gen as p256_key_gen;
368pub use p256::validate_scalar as p256_validate_scalar;
369
370pub fn derive(
373 alg: Algorithm,
374 point: impl AsRef<[u8]>,
375 scalar: impl AsRef<[u8]>,
376) -> Result<Vec<u8>, Error> {
377 match alg {
378 Algorithm::X25519 => {
379 x25519::derive(&point.as_ref().try_into()?, &scalar.as_ref().try_into()?)
380 .map(|r| r.0.into())
381 }
382 Algorithm::P256 => {
383 let point = p256::prepare_public_key(point.as_ref())?;
384 let scalar = hacl::p256::validate_scalar_slice(scalar.as_ref())
385 .map_err(|_| Error::InvalidScalar)?;
386
387 p256::derive(&point, &scalar).map(|r| r.0.into())
388 }
389 _ => Err(Error::UnknownAlgorithm),
390 }
391}
392
393pub(crate) fn p256_derive(
394 point: &p256::PublicKey,
395 scalar: &p256::PrivateKey,
396) -> Result<p256::PublicKey, Error> {
397 p256::validate_point(point)?;
398 p256::validate_scalar(scalar)?;
399
400 p256::derive(&point, &scalar)
401}
402
403pub fn secret_to_public(alg: Algorithm, scalar: impl AsRef<[u8]>) -> Result<Vec<u8>, Error> {
405 match alg {
406 Algorithm::X25519 => {
407 x25519::secret_to_public(&scalar.as_ref().try_into()?).map(|r| r.0.into())
408 }
409 Algorithm::P256 => p256::secret_to_public(&scalar.as_ref().try_into()?).map(|r| r.0.into()),
410 _ => Err(Error::UnknownAlgorithm),
411 }
412}
413
414pub fn validate_scalar(alg: Algorithm, s: impl AsRef<[u8]>) -> Result<(), Error> {
416 match alg {
417 Algorithm::X25519 => {
418 if s.as_ref().iter().all(|&b| b == 0) {
419 Err(Error::InvalidScalar)
420 } else {
421 Ok(())
422 }
423 }
424 Algorithm::P256 => p256::validate_scalar(&s.as_ref().try_into()?),
425 _ => Err(Error::UnknownAlgorithm),
426 }
427}
428
429use rand::{CryptoRng, Rng};
430
431pub fn generate_secret(alg: Algorithm, rng: &mut (impl CryptoRng + Rng)) -> Result<Vec<u8>, Error> {
436 match alg {
437 Algorithm::X25519 => x25519::generate_secret(rng).map(|k| k.0.to_vec()),
438 Algorithm::P256 => p256::generate_secret(rng).map(|k| k.0.to_vec()),
439 _ => Err(Error::UnknownAlgorithm),
440 }
441}
442
443pub fn key_gen(
447 alg: Algorithm,
448 rng: &mut (impl CryptoRng + Rng),
449) -> Result<(Vec<u8>, Vec<u8>), Error> {
450 let sk = generate_secret(alg, rng)?;
451 let pk = secret_to_public(alg, &sk)?;
452 Ok((sk, pk))
453}