1use rand::{CryptoRng, Rng, RngCore};
8
9use crate::{
10 ecdh,
11 hacl::{self, ed25519, p256},
12};
13
14use self::rsa_pss::RsaPssSignature;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum Error {
19 SigningError,
20 InvalidSignature,
21 KeyGenError,
22 InvalidKey,
23 InputTooLarge,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum DigestAlgorithm {
29 Sha256,
30 Sha384,
31 Sha512,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum Algorithm {
37 EcDsaP256(DigestAlgorithm),
38 Ed25519,
39 RsaPss(DigestAlgorithm),
40}
41
42#[derive(Debug)]
44pub enum Signature {
45 EcDsaP256(EcDsaP256Signature),
46 Ed25519(Ed25519Signature),
47 RsaPss(RsaPssSignature),
48}
49
50impl Signature {
51 pub fn into_vec(self) -> Vec<u8> {
56 match self {
57 Signature::EcDsaP256(s) => {
58 let mut out = s.r.to_vec();
59 out.extend_from_slice(&s.s);
60 out
61 }
62 Signature::Ed25519(s) => s.signature.to_vec(),
63 Signature::RsaPss(s) => s.value,
64 }
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub struct EcDsaP256Signature {
71 r: [u8; 32],
72 s: [u8; 32],
73 alg: Algorithm,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub struct Ed25519Signature {
79 signature: [u8; 64],
80}
81
82pub mod rsa_pss {
83 use libcrux_hacl::{
84 hacl_free, Hacl_RSAPSS_new_rsapss_load_pkey, Hacl_RSAPSS_new_rsapss_load_skey,
85 Hacl_RSAPSS_rsapss_sign, Hacl_RSAPSS_rsapss_verify,
86 };
87
88 use super::{DigestAlgorithm, Error};
89
90 #[derive(Debug, Clone, PartialEq, Eq)]
92 pub struct RsaPssSignature {
93 pub(super) value: Vec<u8>,
94 }
95
96 impl RsaPssSignature {
97 pub fn as_bytes(&self) -> &[u8] {
99 &self.value
100 }
101 }
102
103 impl From<&[u8]> for RsaPssSignature {
104 fn from(value: &[u8]) -> Self {
105 Self {
106 value: value.to_vec(),
107 }
108 }
109 }
110
111 impl<const L: usize> From<[u8; L]> for RsaPssSignature {
112 fn from(value: [u8; L]) -> Self {
113 Self {
114 value: value.to_vec(),
115 }
116 }
117 }
118
119 impl From<Vec<u8>> for RsaPssSignature {
120 fn from(value: Vec<u8>) -> Self {
121 Self { value }
122 }
123 }
124
125 #[derive(Debug, Clone, PartialEq, Eq)]
127 pub struct RsaPssPublicKey {
128 n: Vec<u8>,
129 }
130
131 fn rsa_pss_digest(hash_algorithm: DigestAlgorithm) -> u8 {
132 match hash_algorithm {
133 DigestAlgorithm::Sha256 => libcrux_hacl::Spec_Hash_Definitions_SHA2_256 as u8,
134 DigestAlgorithm::Sha384 => libcrux_hacl::Spec_Hash_Definitions_SHA2_384 as u8,
135 DigestAlgorithm::Sha512 => libcrux_hacl::Spec_Hash_Definitions_SHA2_512 as u8,
136 }
137 }
138
139 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
142 #[repr(usize)]
143 pub enum RsaPssKeySize {
144 N2048 = 256,
146
147 N3072 = 384,
149
150 N4096 = 512,
152
153 N6144 = 768,
155
156 N8192 = 1024,
158 }
159
160 const E_BITS: u32 = 24;
162
163 const E: [u8; 3] = [0x01, 0x00, 0x01];
165
166 impl RsaPssPublicKey {
167 pub fn new(key_size: RsaPssKeySize, n: &[u8]) -> Result<Self, Error> {
168 if n.len() != key_size as usize {
169 return Err(Error::InvalidKey);
170 }
171 Ok(Self { n: n.into() })
172 }
173
174 #[must_use = "The result of the signature verification must be used."]
180 pub fn verify(
181 &self,
182 hash_algorithm: DigestAlgorithm,
183 signature: &RsaPssSignature,
184 msg: &[u8],
185 salt_len: usize,
186 ) -> Result<(), Error> {
187 let key_size_bits = (self.n.len() as u32) * 8;
188 unsafe {
189 let pkey = Hacl_RSAPSS_new_rsapss_load_pkey(
190 key_size_bits,
191 E_BITS,
192 self.n.as_ptr() as _,
193 E.as_ptr() as _,
194 );
195 if Hacl_RSAPSS_rsapss_verify(
196 rsa_pss_digest(hash_algorithm),
197 key_size_bits,
198 E_BITS,
199 pkey,
200 salt_len as u32,
201 signature.value.len() as u32,
202 signature.value.as_ptr() as _,
203 msg.len() as u32,
204 msg.as_ptr() as _,
205 ) {
206 return Ok(());
207 }
208 }
209 Err(Error::InvalidSignature)
210 }
211 }
212
213 pub struct RsaPssPrivateKey<'a> {
217 pk: &'a RsaPssPublicKey,
218 d: Vec<u8>,
219 }
220
221 impl<'a> RsaPssPrivateKey<'a> {
222 pub fn new(pk: &'a RsaPssPublicKey, d: &[u8]) -> Result<Self, Error> {
227 if pk.n.len() != d.len() {
228 return Err(Error::InvalidKey);
229 }
230 Ok(Self { pk, d: d.into() })
231 }
232
233 pub fn sign(
239 &self,
240 hash_algorithm: DigestAlgorithm,
241 salt: &[u8],
242 msg: &[u8],
243 ) -> Result<RsaPssSignature, Error> {
244 if salt.len() > (u32::MAX as usize) || msg.len() > (u32::MAX as usize) {
245 return Err(Error::InputTooLarge);
246 }
247
248 let key_len = self.d.len();
249 let mut signature = vec![0; key_len];
250 let key_size_bits = (key_len as u32) * 8;
251
252 unsafe {
253 let s_key = Hacl_RSAPSS_new_rsapss_load_skey(
254 key_size_bits,
255 E_BITS,
256 key_size_bits,
257 self.pk.n.as_ptr() as _,
258 E.as_ptr() as _,
259 self.d.as_ptr() as _,
260 );
261
262 if !Hacl_RSAPSS_rsapss_sign(
263 rsa_pss_digest(hash_algorithm),
264 key_size_bits,
265 E_BITS,
266 key_size_bits,
267 s_key,
268 salt.len() as u32,
269 salt.as_ptr() as _,
270 msg.len() as u32,
271 msg.as_ptr() as _,
272 signature.as_mut_ptr(),
273 ) {
274 hacl_free(s_key as _);
275 return Err(Error::SigningError);
276 }
277 hacl_free(s_key as _);
278 }
279 Ok(RsaPssSignature { value: signature })
280 }
281 }
282}
283
284impl Ed25519Signature {
285 pub fn from_bytes(signature: [u8; 64]) -> Self {
287 Self { signature }
288 }
289
290 pub fn from_slice(bytes: &[u8]) -> Result<Self, Error> {
294 Ok(Self {
295 signature: bytes.try_into().map_err(|_| Error::InvalidSignature)?,
296 })
297 }
298
299 pub fn as_bytes(&self) -> &[u8; 64] {
301 &self.signature
302 }
303}
304
305impl EcDsaP256Signature {
306 pub fn from_raw(r: [u8; 32], s: [u8; 32], alg: Algorithm) -> Self {
308 Self { r, s, alg }
309 }
310
311 pub fn from_bytes(signature_bytes: [u8; 64], alg: Algorithm) -> Self {
313 Self {
314 r: signature_bytes[0..32].try_into().unwrap(),
315 s: signature_bytes[32..].try_into().unwrap(),
316 alg,
317 }
318 }
319
320 pub fn as_bytes(&self) -> (&[u8; 32], &[u8; 32]) {
322 (&self.r, &self.s)
323 }
324}
325
326fn ecdsa_p256_sign_prep(
328 private_key: &[u8],
329 rng: &mut (impl CryptoRng + RngCore),
330) -> Result<(ecdh::p256::PrivateKey, [u8; 32]), Error> {
331 let private_key = p256::validate_scalar_slice(private_key).map_err(|_| Error::SigningError)?;
332
333 let mut nonce = [0u8; 32];
334 loop {
335 rng.try_fill_bytes(&mut nonce)
336 .map_err(|_| Error::SigningError)?;
337 if p256::validate_scalar_slice(&nonce).is_ok() {
339 break;
340 }
341 }
342
343 Ok((private_key, nonce))
344}
345
346fn ecdsa_p256_sign_post(signature: [u8; 64], alg: Algorithm) -> Result<Signature, Error> {
348 Ok(Signature::EcDsaP256(EcDsaP256Signature {
349 r: signature[..32]
350 .try_into()
351 .map_err(|_| Error::SigningError)?,
352 s: signature[32..]
353 .try_into()
354 .map_err(|_| Error::SigningError)?,
355 alg,
356 }))
357}
358
359fn into_signing_error(_e: impl Into<hacl::Error>) -> Error {
360 Error::SigningError
361}
362
363pub fn sign(
367 alg: Algorithm,
368 payload: &[u8],
369 private_key: &[u8],
370 rng: &mut (impl CryptoRng + RngCore),
371) -> Result<Signature, Error> {
372 let signature = match alg {
373 Algorithm::EcDsaP256(DigestAlgorithm::Sha256) => {
374 let (private_key, nonce) = ecdsa_p256_sign_prep(private_key, rng)?;
375 ecdsa_p256_sign_post(
376 p256::ecdsa::sign_sha256(payload, private_key.as_ref(), &nonce)
377 .map_err(into_signing_error)?,
378 alg,
379 )?
380 }
381 Algorithm::EcDsaP256(DigestAlgorithm::Sha384) => {
382 let (private_key, nonce) = ecdsa_p256_sign_prep(private_key, rng)?;
383 ecdsa_p256_sign_post(
384 p256::ecdsa::sign_sha384(payload, private_key.as_ref(), &nonce)
385 .map_err(into_signing_error)?,
386 alg,
387 )?
388 }
389 Algorithm::EcDsaP256(DigestAlgorithm::Sha512) => {
390 let (private_key, nonce) = ecdsa_p256_sign_prep(private_key, rng)?;
391 ecdsa_p256_sign_post(
392 p256::ecdsa::sign_sha512(payload, private_key.as_ref(), &nonce)
393 .map_err(into_signing_error)?,
394 alg,
395 )?
396 }
397 Algorithm::Ed25519 => {
398 let signature = ed25519::sign(
399 payload,
400 private_key.try_into().map_err(|_| Error::SigningError)?,
401 )
402 .map_err(into_signing_error)?;
403 Signature::Ed25519(Ed25519Signature { signature })
404 }
405 Algorithm::RsaPss(_) => {
406 todo!()
407 }
408 };
409
410 Ok(signature)
411}
412
413fn into_verify_error(_e: impl Into<hacl::Error>) -> Error {
414 Error::InvalidSignature
415}
416
417fn ecdsa_p256_verify_prep(public_key: &[u8]) -> Result<[u8; 64], Error> {
419 if public_key.is_empty() {
420 return Err(Error::SigningError);
421 }
422
423 let pk = if let Ok(pk) = p256::uncompressed_to_coordinates(public_key) {
425 pk
426 } else {
427 if let Ok(pk) = p256::compressed_to_coordinates(public_key) {
429 pk
430 } else {
431 public_key.try_into().map_err(|_| Error::InvalidSignature)?
433 }
434 };
435
436 p256::validate_point(ecdh::p256::PublicKey(pk))
437 .map(|()| pk)
438 .map_err(into_verify_error)
439}
440
441pub fn verify(payload: &[u8], signature: &Signature, public_key: &[u8]) -> Result<(), Error> {
445 match signature {
446 Signature::EcDsaP256(signature) => match signature.alg {
447 Algorithm::EcDsaP256(DigestAlgorithm::Sha256) => {
448 let pk = ecdsa_p256_verify_prep(public_key)?;
449 p256::ecdsa::verify_sha256(payload, &pk, &signature.r, &signature.s)
450 }
451 Algorithm::EcDsaP256(DigestAlgorithm::Sha384) => {
452 let pk = ecdsa_p256_verify_prep(public_key)?;
453 p256::ecdsa::verify_sha384(payload, &pk, &signature.r, &signature.s)
454 }
455 Algorithm::EcDsaP256(DigestAlgorithm::Sha512) => {
456 let pk = ecdsa_p256_verify_prep(public_key)?;
457 p256::ecdsa::verify_sha512(payload, &pk, &signature.r, &signature.s)
458 }
459 _ => Err(p256::Error::InvalidInput),
460 }
461 .map_err(into_verify_error),
462 Signature::Ed25519(signature) => {
463 let public_key = public_key.try_into().map_err(|_| Error::InvalidSignature)?;
464 ed25519::verify(payload, public_key, &signature.signature).map_err(into_verify_error)
465 }
466 Signature::RsaPss(_) => todo!(),
467 }
468}
469
470pub fn key_gen(
474 alg: Algorithm,
475 rng: &mut (impl CryptoRng + Rng),
476) -> Result<(Vec<u8>, Vec<u8>), Error> {
477 match alg {
478 Algorithm::EcDsaP256(_) => {
479 ecdh::key_gen(ecdh::Algorithm::P256, rng).map_err(|_| Error::KeyGenError)
480 }
481 Algorithm::Ed25519 => {
482 const LIMIT: usize = 100;
483 let mut sk = [0u8; 32];
484 for _ in 0..LIMIT {
485 rng.try_fill_bytes(&mut sk)
486 .map_err(|_| Error::KeyGenError)?;
487
488 if sk.iter().all(|&b| b == 0) {
490 sk = [0u8; 32];
491 continue;
492 }
493
494 sk[0] = sk[0] & 248u8;
496 sk[31] = sk[31] & 127u8;
497 sk[31] = sk[31] | 64u8;
498
499 break;
500 }
501 let pk = ed25519::secret_to_public(&sk);
502
503 Ok((sk.to_vec(), pk.to_vec()))
504 }
505 Algorithm::RsaPss(_) => todo!(),
506 }
507}