libcrux_ecdh/hacl/
p256.rs1use libcrux_p256::{
2 compressed_to_raw, dh_initiator, dh_responder, uncompressed_to_raw, validate_private_key,
3 validate_public_key,
4};
5
6use crate::p256_internal::PrivateKey;
7
8#[derive(Debug, PartialEq, Eq, Clone, Copy)]
9pub enum Error {
10 InvalidInput,
11 InvalidScalar,
12 InvalidPoint,
13 NoCompressedPoint,
14 NoUnCompressedPoint,
15}
16
17pub fn uncompressed_to_coordinates(point: &[u8]) -> Result<[u8; 64], Error> {
20 let mut concat_point = [0u8; 64];
21 if point.len() >= 65 {
22 let ok = uncompressed_to_raw(point, &mut concat_point);
23 if ok {
24 Ok(concat_point)
25 } else {
26 Err(Error::InvalidInput)
27 }
28 } else {
29 Err(Error::NoCompressedPoint)
30 }
31}
32
33pub fn compressed_to_coordinates(point: &[u8]) -> Result<[u8; 64], Error> {
36 let mut concat_point = [0u8; 64];
37 if point.len() >= 33 {
38 let ok = compressed_to_raw(point, &mut concat_point);
39 if ok {
40 Ok(concat_point)
41 } else {
42 Err(Error::InvalidInput)
43 }
44 } else {
45 Err(Error::NoUnCompressedPoint)
46 }
47}
48
49pub fn validate_point(point: impl AsRef<[u8; 64]>) -> Result<(), Error> {
54 if validate_public_key(point.as_ref()) {
55 Ok(())
56 } else {
57 Err(Error::InvalidPoint)
58 }
59}
60
61pub fn validate_scalar(scalar: &impl AsRef<[u8; 32]>) -> Result<(), Error> {
65 validate_scalar_(scalar.as_ref())
66}
67
68pub fn validate_scalar_(scalar: &[u8; 32]) -> Result<(), Error> {
72 if scalar.as_ref().iter().all(|b| *b == 0) {
73 return Err(Error::InvalidScalar);
74 }
75
76 if validate_private_key(scalar.as_ref()) {
78 Ok(())
79 } else {
80 Err(Error::InvalidScalar)
81 }
82}
83
84pub fn validate_scalar_slice(scalar: &[u8]) -> Result<PrivateKey, Error> {
86 if scalar.is_empty() {
87 return Err(Error::InvalidScalar);
88 }
89
90 let mut private = [0u8; 32];
91 let sk_len = if scalar.len() >= 32 { 32 } else { scalar.len() };
93 for i in 0..sk_len {
94 private[31 - i] = scalar[scalar.len() - 1 - i];
95 }
96
97 validate_scalar_(&private).map(|_| PrivateKey(private))
98}
99
100pub fn ecdh(
104 private_key: impl AsRef<[u8; 32]>,
105 public_key: impl AsRef<[u8; 64]>,
106) -> Result<[u8; 64], Error> {
107 let mut shared = [0u8; 64];
108 let ok = dh_responder(&mut shared, public_key.as_ref(), private_key.as_ref());
109 if !ok {
110 Err(Error::InvalidInput)
111 } else {
112 Ok(shared)
113 }
114}
115
116pub fn secret_to_public(s: impl AsRef<[u8; 32]>) -> Result<[u8; 64], Error> {
120 validate_scalar(&s)?;
121
122 let mut out = [0u8; 64];
123 if dh_initiator(&mut out, s.as_ref()) {
124 Ok(out)
125 } else {
126 Err(Error::InvalidScalar)
127 }
128}