1#![deny(missing_docs)]
51#![deny(unsafe_code)]
52
53use alloc::{vec, vec::Vec};
54use core::fmt;
55
56use zeroize::Zeroizing;
57
58use crate::{
59 falcon as falcon_api,
60 rng::get_seed,
61 shake::{i_shake256_flip, i_shake256_init, i_shake256_inject, InnerShake256Context},
62};
63
64#[doc(hidden)]
73pub fn sha256_public(data: &[u8]) -> [u8; 32] {
74 sha256(data)
75}
76
77#[doc(hidden)]
81pub fn sha512_public(data: &[u8]) -> [u8; 64] {
82 sha512(data)
83}
84
85fn sha256(data: &[u8]) -> [u8; 32] {
87 let mut h: [u32; 8] = [
89 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab,
90 0x5be0cd19,
91 ];
92 const K: [u32; 64] = [
94 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4,
95 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,
96 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f,
97 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
98 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
99 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
100 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116,
101 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
102 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
103 0xc67178f2,
104 ];
105
106 let bit_len = (data.len() as u64).wrapping_mul(8);
108 let mut msg: Vec<u8> = Vec::with_capacity(data.len() + 64);
109 msg.extend_from_slice(data);
110 msg.push(0x80);
111 while (msg.len() % 64) != 56 {
112 msg.push(0x00);
113 }
114 msg.extend_from_slice(&bit_len.to_be_bytes());
115
116 for chunk in msg.chunks(64) {
118 let mut w = [0u32; 64];
119 for i in 0..16 {
120 w[i] = u32::from_be_bytes([
121 chunk[4 * i],
122 chunk[4 * i + 1],
123 chunk[4 * i + 2],
124 chunk[4 * i + 3],
125 ]);
126 }
127 for i in 16..64 {
128 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
129 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
130 w[i] = w[i - 16]
131 .wrapping_add(s0)
132 .wrapping_add(w[i - 7])
133 .wrapping_add(s1);
134 }
135 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] =
136 [h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]];
137 for i in 0..64 {
138 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
139 let ch = (e & f) ^ ((!e) & g);
140 let temp1 = hh
141 .wrapping_add(s1)
142 .wrapping_add(ch)
143 .wrapping_add(K[i])
144 .wrapping_add(w[i]);
145 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
146 let maj = (a & b) ^ (a & c) ^ (b & c);
147 let temp2 = s0.wrapping_add(maj);
148 hh = g;
149 g = f;
150 f = e;
151 e = d.wrapping_add(temp1);
152 d = c;
153 c = b;
154 b = a;
155 a = temp1.wrapping_add(temp2);
156 }
157 h[0] = h[0].wrapping_add(a);
158 h[1] = h[1].wrapping_add(b);
159 h[2] = h[2].wrapping_add(c);
160 h[3] = h[3].wrapping_add(d);
161 h[4] = h[4].wrapping_add(e);
162 h[5] = h[5].wrapping_add(f);
163 h[6] = h[6].wrapping_add(g);
164 h[7] = h[7].wrapping_add(hh);
165 }
166
167 let mut out = [0u8; 32];
168 for (i, &v) in h.iter().enumerate() {
169 out[4 * i..4 * i + 4].copy_from_slice(&v.to_be_bytes());
170 }
171 out
172}
173
174fn sha512(data: &[u8]) -> [u8; 64] {
176 let mut h: [u64; 8] = [
177 0x6a09e667f3bcc908,
178 0xbb67ae8584caa73b,
179 0x3c6ef372fe94f82b,
180 0xa54ff53a5f1d36f1,
181 0x510e527fade682d1,
182 0x9b05688c2b3e6c1f,
183 0x1f83d9abfb41bd6b,
184 0x5be0cd19137e2179,
185 ];
186 const K: [u64; 80] = [
187 0x428a2f98d728ae22,
188 0x7137449123ef65cd,
189 0xb5c0fbcfec4d3b2f,
190 0xe9b5dba58189dbbc,
191 0x3956c25bf348b538,
192 0x59f111f1b605d019,
193 0x923f82a4af194f9b,
194 0xab1c5ed5da6d8118,
195 0xd807aa98a3030242,
196 0x12835b0145706fbe,
197 0x243185be4ee4b28c,
198 0x550c7dc3d5ffb4e2,
199 0x72be5d74f27b896f,
200 0x80deb1fe3b1696b1,
201 0x9bdc06a725c71235,
202 0xc19bf174cf692694,
203 0xe49b69c19ef14ad2,
204 0xefbe4786384f25e3,
205 0x0fc19dc68b8cd5b5,
206 0x240ca1cc77ac9c65,
207 0x2de92c6f592b0275,
208 0x4a7484aa6ea6e483,
209 0x5cb0a9dcbd41fbd4,
210 0x76f988da831153b5,
211 0x983e5152ee66dfab,
212 0xa831c66d2db43210,
213 0xb00327c898fb213f,
214 0xbf597fc7beef0ee4,
215 0xc6e00bf33da88fc2,
216 0xd5a79147930aa725,
217 0x06ca6351e003826f,
218 0x142929670a0e6e70,
219 0x27b70a8546d22ffc,
220 0x2e1b21385c26c926,
221 0x4d2c6dfc5ac42aed,
222 0x53380d139d95b3df,
223 0x650a73548baf63de,
224 0x766a0abb3c77b2a8,
225 0x81c2c92e47edaee6,
226 0x92722c851482353b,
227 0xa2bfe8a14cf10364,
228 0xa81a664bbc423001,
229 0xc24b8b70d0f89791,
230 0xc76c51a30654be30,
231 0xd192e819d6ef5218,
232 0xd69906245565a910,
233 0xf40e35855771202a,
234 0x106aa07032bbd1b8,
235 0x19a4c116b8d2d0c8,
236 0x1e376c085141ab53,
237 0x2748774cdf8eeb99,
238 0x34b0bcb5e19b48a8,
239 0x391c0cb3c5c95a63,
240 0x4ed8aa4ae3418acb,
241 0x5b9cca4f7763e373,
242 0x682e6ff3d6b2b8a3,
243 0x748f82ee5defb2fc,
244 0x78a5636f43172f60,
245 0x84c87814a1f0ab72,
246 0x8cc702081a6439ec,
247 0x90befffa23631e28,
248 0xa4506cebde82bde9,
249 0xbef9a3f7b2c67915,
250 0xc67178f2e372532b,
251 0xca273eceea26619c,
252 0xd186b8c721c0c207,
253 0xeada7dd6cde0eb1e,
254 0xf57d4f7fee6ed178,
255 0x06f067aa72176fba,
256 0x0a637dc5a2c898a6,
257 0x113f9804bef90dae,
258 0x1b710b35131c471b,
259 0x28db77f523047d84,
260 0x32caab7b40c72493,
261 0x3c9ebe0a15c9bebc,
262 0x431d67c49c100d4c,
263 0x4cc5d4becb3e42b6,
264 0x597f299cfc657e2a,
265 0x5fcb6fab3ad6faec,
266 0x6c44198c4a475817,
267 ];
268
269 let bit_len = (data.len() as u128).wrapping_mul(8);
270 let mut msg: Vec<u8> = Vec::with_capacity(data.len() + 128);
271 msg.extend_from_slice(data);
272 msg.push(0x80);
273 while (msg.len() % 128) != 112 {
274 msg.push(0x00);
275 }
276 msg.extend_from_slice(&[0u8; 8]); msg.extend_from_slice(&(bit_len as u64).to_be_bytes());
278
279 for chunk in msg.chunks(128) {
280 let mut w = [0u64; 80];
281 for i in 0..16 {
282 let b = &chunk[8 * i..8 * i + 8];
283 w[i] = u64::from_be_bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]]);
284 }
285 for i in 16..80 {
286 let s0 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
287 let s1 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
288 w[i] = w[i - 16]
289 .wrapping_add(s0)
290 .wrapping_add(w[i - 7])
291 .wrapping_add(s1);
292 }
293 let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh] =
294 [h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]];
295 for i in 0..80 {
296 let s1 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
297 let ch = (e & f) ^ ((!e) & g);
298 let t1 = hh
299 .wrapping_add(s1)
300 .wrapping_add(ch)
301 .wrapping_add(K[i])
302 .wrapping_add(w[i]);
303 let s0 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
304 let maj = (a & b) ^ (a & c) ^ (b & c);
305 let t2 = s0.wrapping_add(maj);
306 hh = g;
307 g = f;
308 f = e;
309 e = d.wrapping_add(t1);
310 d = c;
311 c = b;
312 b = a;
313 a = t1.wrapping_add(t2);
314 }
315 h[0] = h[0].wrapping_add(a);
316 h[1] = h[1].wrapping_add(b);
317 h[2] = h[2].wrapping_add(c);
318 h[3] = h[3].wrapping_add(d);
319 h[4] = h[4].wrapping_add(e);
320 h[5] = h[5].wrapping_add(f);
321 h[6] = h[6].wrapping_add(g);
322 h[7] = h[7].wrapping_add(hh);
323 }
324
325 let mut out = [0u8; 64];
326 for (i, &v) in h.iter().enumerate() {
327 out[8 * i..8 * i + 8].copy_from_slice(&v.to_be_bytes());
328 }
329 out
330}
331
332const OID_SHA256: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01];
338const OID_SHA512: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03];
340
341#[derive(Debug, Clone, Copy, PartialEq, Eq)]
351#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
352pub enum PreHashAlgorithm {
353 Sha256,
355 Sha512,
357}
358
359impl PreHashAlgorithm {
360 fn oid(self) -> &'static [u8] {
361 match self {
362 PreHashAlgorithm::Sha256 => OID_SHA256,
363 PreHashAlgorithm::Sha512 => OID_SHA512,
364 }
365 }
366
367 fn hash(self, msg: &[u8]) -> Vec<u8> {
368 match self {
369 PreHashAlgorithm::Sha256 => sha256(msg).to_vec(),
370 PreHashAlgorithm::Sha512 => sha512(msg).to_vec(),
371 }
372 }
373}
374
375#[derive(Debug, Clone, Copy, PartialEq, Eq)]
400#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
401pub enum DomainSeparation<'a> {
402 None,
404 Context(&'a [u8]),
406 Prehashed {
409 alg: PreHashAlgorithm,
411 context: &'a [u8],
413 },
414}
415
416impl<'a> DomainSeparation<'a> {
417 fn validate_context(ctx: &[u8]) -> Result<(), FalconError> {
419 if ctx.len() > 255 {
420 return Err(FalconError::BadArgument);
421 }
422 Ok(())
423 }
424
425 pub(crate) fn validate(&self) -> Result<(), FalconError> {
427 match self {
428 DomainSeparation::None => Ok(()),
429 DomainSeparation::Context(ctx) => Self::validate_context(ctx),
430 DomainSeparation::Prehashed { context, .. } => Self::validate_context(context),
431 }
432 }
433
434 fn ph_flag(&self) -> u8 {
436 match self {
437 DomainSeparation::Prehashed { .. } => 0x01,
438 _ => 0x00,
439 }
440 }
441
442 pub(crate) fn inject_header(&self, sc: &mut InnerShake256Context) {
447 let (ctx, oid) = match self {
448 DomainSeparation::None => (&b""[..], None),
449 DomainSeparation::Context(c) => (*c, None),
450 DomainSeparation::Prehashed { alg, context } => (*context, Some(alg.oid())),
451 };
452 let len = ctx.len().min(255) as u8;
454 i_shake256_inject(sc, &[self.ph_flag(), len]);
455 if len > 0 {
456 i_shake256_inject(sc, &ctx[..len as usize]);
457 }
458 if let Some(o) = oid {
460 i_shake256_inject(sc, o);
461 }
462 }
463
464 pub(crate) fn inject_message(&self, sc: &mut InnerShake256Context, message: &[u8]) {
467 match self {
468 DomainSeparation::Prehashed { alg, .. } => {
469 let digest = alg.hash(message);
470 falcon_api::shake256_inject(sc, &digest);
471 }
472 _ => {
473 falcon_api::shake256_inject(sc, message);
474 }
475 }
476 }
477
478 pub(crate) fn inject(&self, sc: &mut InnerShake256Context, message: &[u8]) {
480 self.inject_header(sc);
481 self.inject_message(sc, message);
482 }
483}
484
485#[derive(Debug, Clone, Copy, PartialEq, Eq)]
491#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
492pub enum FalconError {
493 RandomError,
495 SizeError,
497 FormatError,
499 BadSignature,
501 BadArgument,
503 InternalError,
505}
506
507impl fmt::Display for FalconError {
508 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
509 match self {
510 FalconError::RandomError => write!(f, "random number generation failed"),
511 FalconError::SizeError => write!(f, "buffer size error"),
512 FalconError::FormatError => write!(f, "invalid format"),
513 FalconError::BadSignature => write!(f, "invalid signature"),
514 FalconError::BadArgument => write!(f, "invalid argument"),
515 FalconError::InternalError => write!(f, "internal error"),
516 }
517 }
518}
519
520#[cfg(feature = "std")]
521impl std::error::Error for FalconError {}
522
523fn translate_error(rc: i32) -> FalconError {
524 match rc {
525 falcon_api::FALCON_ERR_RANDOM => FalconError::RandomError,
526 falcon_api::FALCON_ERR_SIZE => FalconError::SizeError,
527 falcon_api::FALCON_ERR_FORMAT => FalconError::FormatError,
528 falcon_api::FALCON_ERR_BADSIG => FalconError::BadSignature,
529 falcon_api::FALCON_ERR_BADARG => FalconError::BadArgument,
530 falcon_api::FALCON_ERR_INTERNAL => FalconError::InternalError,
531 _ => FalconError::InternalError,
532 }
533}
534
535#[derive(Clone)]
549#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
550pub struct FnDsaKeyPair {
551 privkey: Zeroizing<Vec<u8>>,
553 pubkey: Vec<u8>,
555 logn: u32,
557}
558
559impl fmt::Debug for FnDsaKeyPair {
560 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561 f.debug_struct("FnDsaKeyPair")
562 .field("privkey", &"[REDACTED]")
563 .field("pubkey_len", &self.pubkey.len())
564 .field("logn", &self.logn)
565 .finish()
566 }
567}
568
569pub type FalconKeyPair = FnDsaKeyPair;
571
572impl FnDsaKeyPair {
573 #[inline]
574 const fn is_fips_logn(logn: u32) -> bool {
575 matches!(logn, 9 | 10)
576 }
577
578 pub fn generate(logn: u32) -> Result<Self, FalconError> {
582 if !Self::is_fips_logn(logn) {
583 return Err(FalconError::BadArgument);
584 }
585 let mut seed = Zeroizing::new([0u8; 48]);
586 if !get_seed(&mut *seed) {
587 return Err(FalconError::RandomError);
588 }
589 Self::generate_deterministic(&seed[..], logn)
590 }
591
592 pub fn generate_deterministic(seed: &[u8], logn: u32) -> Result<Self, FalconError> {
594 if !Self::is_fips_logn(logn) {
595 return Err(FalconError::BadArgument);
596 }
597 let sk_len = falcon_api::falcon_privkey_size(logn);
598 let pk_len = falcon_api::falcon_pubkey_size(logn);
599 let tmp_len = falcon_api::falcon_tmpsize_keygen(logn);
600
601 let mut rng = InnerShake256Context::new();
602 i_shake256_init(&mut rng);
603 i_shake256_inject(&mut rng, seed);
604 i_shake256_flip(&mut rng);
605
606 let mut privkey = vec![0u8; sk_len];
607 let mut pubkey = vec![0u8; pk_len];
608 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
609
610 let rc = falcon_api::falcon_keygen_make(
611 &mut rng,
612 logn,
613 &mut privkey,
614 Some(&mut pubkey),
615 &mut tmp,
616 );
617 if rc != 0 {
618 return Err(translate_error(rc));
619 }
620 Ok(FnDsaKeyPair {
621 privkey: Zeroizing::new(privkey),
622 pubkey,
623 logn,
624 })
625 }
626
627 pub fn from_keys(privkey: &[u8], pubkey: &[u8]) -> Result<Self, FalconError> {
629 if privkey.is_empty() || pubkey.is_empty() {
630 return Err(FalconError::FormatError);
631 }
632 let sk_logn = falcon_api::falcon_get_logn(privkey);
633 let pk_logn = falcon_api::falcon_get_logn(pubkey);
634 if sk_logn < 0 || pk_logn < 0 {
635 return Err(FalconError::FormatError);
636 }
637 if (privkey[0] & 0xF0) != 0x50 {
638 return Err(FalconError::FormatError);
639 }
640 if (pubkey[0] & 0xF0) != 0x00 {
641 return Err(FalconError::FormatError);
642 }
643 let logn = (sk_logn & 0x0F) as u32;
644 if logn != (pk_logn & 0x0F) as u32 {
645 return Err(FalconError::FormatError);
646 }
647 if !Self::is_fips_logn(logn) {
648 return Err(FalconError::BadArgument);
649 }
650 if privkey.len() != falcon_api::falcon_privkey_size(logn) {
651 return Err(FalconError::FormatError);
652 }
653 if pubkey.len() != falcon_api::falcon_pubkey_size(logn) {
654 return Err(FalconError::FormatError);
655 }
656 Ok(FnDsaKeyPair {
657 privkey: Zeroizing::new(privkey.to_vec()),
658 pubkey: pubkey.to_vec(),
659 logn,
660 })
661 }
662
663 pub fn from_private_key(privkey: &[u8]) -> Result<Self, FalconError> {
665 if privkey.is_empty() {
666 return Err(FalconError::FormatError);
667 }
668 if (privkey[0] & 0xF0) != 0x50 {
669 return Err(FalconError::FormatError);
670 }
671 let logn_val = falcon_api::falcon_get_logn(privkey);
672 if logn_val < 0 {
673 return Err(FalconError::FormatError);
674 }
675 let logn = logn_val as u32;
676 if !Self::is_fips_logn(logn) {
677 return Err(FalconError::BadArgument);
678 }
679 if privkey.len() != falcon_api::falcon_privkey_size(logn) {
680 return Err(FalconError::FormatError);
681 }
682 let pk_len = falcon_api::falcon_pubkey_size(logn);
683 let tmp_len = falcon_api::falcon_tmpsize_makepub(logn);
684 let mut pubkey = vec![0u8; pk_len];
685 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
686 let rc = falcon_api::falcon_make_public(&mut pubkey, privkey, &mut tmp);
687 if rc != 0 {
688 return Err(translate_error(rc));
689 }
690 Ok(FnDsaKeyPair {
691 privkey: Zeroizing::new(privkey.to_vec()),
692 pubkey,
693 logn,
694 })
695 }
696
697 pub fn public_key_from_private(privkey: &[u8]) -> Result<Vec<u8>, FalconError> {
699 Ok(Self::from_private_key(privkey)?.pubkey)
700 }
701
702 pub fn sign(
713 &self,
714 message: &[u8],
715 domain: &DomainSeparation,
716 ) -> Result<FnDsaSignature, FalconError> {
717 domain.validate()?;
718
719 let sig_max = falcon_api::falcon_sig_ct_size(self.logn);
720 let tmp_len = falcon_api::falcon_tmpsize_signdyn(self.logn);
721
722 let mut seed = Zeroizing::new([0u8; 48]);
723 if !get_seed(&mut *seed) {
724 return Err(FalconError::RandomError);
725 }
726 let mut rng = InnerShake256Context::new();
727 i_shake256_init(&mut rng);
728 i_shake256_inject(&mut rng, &*seed);
729 i_shake256_flip(&mut rng);
730
731 let mut sig = vec![0u8; sig_max];
732 let mut sig_len = sig_max;
733 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
734
735 let mut nonce = [0u8; 40];
736 falcon_api::shake256_extract(&mut rng, &mut nonce);
737 let mut hd = InnerShake256Context::new();
738 falcon_api::shake256_init(&mut hd);
739 falcon_api::shake256_inject(&mut hd, &nonce);
740 domain.inject(&mut hd, message);
741
742 let rc = falcon_api::falcon_sign_dyn_finish(
743 &mut rng,
744 &mut sig,
745 &mut sig_len,
746 falcon_api::FALCON_SIG_CT,
747 &self.privkey,
748 &mut hd,
749 &nonce,
750 &mut tmp,
751 );
752 if rc != 0 {
753 return Err(translate_error(rc));
754 }
755 sig.truncate(sig_len);
756 Ok(FnDsaSignature { data: sig })
757 }
758
759 pub fn sign_deterministic(
768 &self,
769 message: &[u8],
770 seed: &[u8],
771 domain: &DomainSeparation,
772 ) -> Result<FnDsaSignature, FalconError> {
773 domain.validate()?;
774
775 let sig_max = falcon_api::falcon_sig_ct_size(self.logn);
776 let tmp_len = falcon_api::falcon_tmpsize_signdyn(self.logn);
777
778 let mut rng = InnerShake256Context::new();
779 i_shake256_init(&mut rng);
780 i_shake256_inject(&mut rng, seed);
781 i_shake256_flip(&mut rng);
782
783 let mut sig = vec![0u8; sig_max];
784 let mut sig_len = sig_max;
785 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
786
787 let mut nonce = [0u8; 40];
788 falcon_api::shake256_extract(&mut rng, &mut nonce);
789 let mut hd = InnerShake256Context::new();
790 falcon_api::shake256_init(&mut hd);
791 falcon_api::shake256_inject(&mut hd, &nonce);
792 domain.inject(&mut hd, message);
793
794 let rc = falcon_api::falcon_sign_dyn_finish(
795 &mut rng,
796 &mut sig,
797 &mut sig_len,
798 falcon_api::FALCON_SIG_CT,
799 &self.privkey,
800 &mut hd,
801 &nonce,
802 &mut tmp,
803 );
804 if rc != 0 {
805 return Err(translate_error(rc));
806 }
807 sig.truncate(sig_len);
808 Ok(FnDsaSignature { data: sig })
809 }
810
811 pub fn public_key(&self) -> &[u8] {
813 &self.pubkey
814 }
815
816 pub fn private_key(&self) -> &[u8] {
820 &self.privkey
821 }
822
823 pub fn logn(&self) -> u32 {
827 self.logn
828 }
829
830 pub fn variant_name(&self) -> &'static str {
832 match self.logn {
833 9 => "FN-DSA-512",
834 10 => "FN-DSA-1024",
835 n => match n {
836 1 => "FN-DSA-2",
837 2 => "FN-DSA-4",
838 3 => "FN-DSA-8",
839 4 => "FN-DSA-16",
840 5 => "FN-DSA-32",
841 6 => "FN-DSA-64",
842 7 => "FN-DSA-128",
843 8 => "FN-DSA-256",
844 _ => "FN-DSA-unknown",
845 },
846 }
847 }
848}
849
850#[derive(Debug, Clone)]
859#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
860pub struct FnDsaSignature {
861 data: Vec<u8>,
862}
863
864pub type FalconSignature = FnDsaSignature;
866
867impl FnDsaSignature {
868 pub fn from_bytes(data: Vec<u8>) -> Result<Self, FalconError> {
874 if data.len() < 41 {
875 return Err(FalconError::FormatError);
876 }
877 let hdr = data[0] & 0xF0;
879 if hdr != 0x30 && hdr != 0x50 {
880 return Err(FalconError::FormatError);
881 }
882 let logn = data[0] & 0x0F;
883 if !FnDsaKeyPair::is_fips_logn(logn as u32) {
884 return Err(FalconError::BadArgument);
885 }
886 Ok(FnDsaSignature { data })
887 }
888
889 pub fn verify(
902 sig: &[u8],
903 pubkey: &[u8],
904 message: &[u8],
905 domain: &DomainSeparation,
906 ) -> Result<(), FalconError> {
907 domain.validate()?;
908
909 if pubkey.is_empty() || sig.is_empty() {
910 return Err(FalconError::FormatError);
911 }
912 let logn_val = falcon_api::falcon_get_logn(pubkey);
913 if logn_val < 0 {
914 return Err(FalconError::FormatError);
915 }
916 let logn = logn_val as u32;
917 if !FnDsaKeyPair::is_fips_logn(logn) {
918 return Err(FalconError::BadArgument);
919 }
920
921 let sig_ct = falcon_api::falcon_sig_ct_size(logn);
923 let sig_padded = falcon_api::falcon_sig_padded_size(logn);
924 let sig_comp_max = falcon_api::falcon_sig_compressed_maxsize(logn);
925 if sig.len() < 41 || sig.len() > sig_ct.max(sig_padded).max(sig_comp_max) {
926 return Err(FalconError::FormatError);
927 }
928
929 let tmp_len = falcon_api::falcon_tmpsize_verify(logn);
930 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
931
932 let mut hd = InnerShake256Context::new();
933 let r = falcon_api::falcon_verify_start(&mut hd, sig);
934 if r < 0 {
935 return Err(translate_error(r));
936 }
937 domain.inject(&mut hd, message);
938 let rc = falcon_api::falcon_verify_finish(sig, 0, pubkey, &mut hd, &mut tmp);
939 if rc != 0 {
940 return Err(translate_error(rc));
941 }
942 Ok(())
943 }
944
945 pub fn to_bytes(&self) -> &[u8] {
947 &self.data
948 }
949
950 pub fn into_bytes(self) -> Vec<u8> {
952 self.data
953 }
954
955 pub fn len(&self) -> usize {
957 self.data.len()
958 }
959
960 pub fn is_empty(&self) -> bool {
962 self.data.is_empty()
963 }
964}
965
966#[derive(Clone)]
990pub struct FnDsaExpandedKey {
991 expanded: Zeroizing<Vec<u8>>,
993 pubkey: Vec<u8>,
995 logn: u32,
997}
998
999impl fmt::Debug for FnDsaExpandedKey {
1000 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1001 f.debug_struct("FnDsaExpandedKey")
1002 .field("expanded", &"[REDACTED]")
1003 .field("pubkey_len", &self.pubkey.len())
1004 .field("logn", &self.logn)
1005 .finish()
1006 }
1007}
1008
1009impl FnDsaKeyPair {
1010 pub fn expand(&self) -> Result<FnDsaExpandedKey, FalconError> {
1015 let logn = self.logn;
1016 let ek_len = falcon_api::falcon_expandedkey_size(logn);
1017 let tmp_len = falcon_api::falcon_tmpsize_expandpriv(logn);
1018 let mut expanded = vec![0u8; ek_len];
1019 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
1020 let rc = falcon_api::falcon_expand_privkey(&mut expanded, &self.privkey, &mut tmp);
1021 if rc != 0 {
1022 return Err(translate_error(rc));
1023 }
1024 Ok(FnDsaExpandedKey {
1025 expanded: Zeroizing::new(expanded),
1026 pubkey: self.pubkey.clone(),
1027 logn,
1028 })
1029 }
1030}
1031
1032impl FnDsaExpandedKey {
1033 pub fn sign(
1035 &self,
1036 message: &[u8],
1037 domain: &DomainSeparation<'_>,
1038 ) -> Result<FnDsaSignature, FalconError> {
1039 domain.validate()?;
1040 let logn = self.logn;
1041 let sig_max = falcon_api::falcon_sig_ct_size(logn);
1042 let tmp_len = falcon_api::falcon_tmpsize_signtree(logn);
1043 let mut sig = vec![0u8; sig_max];
1044 let mut sig_len = sig_max;
1045 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
1046
1047 let mut seed = Zeroizing::new([0u8; 48]);
1048 if !get_seed(&mut *seed) {
1049 return Err(FalconError::RandomError);
1050 }
1051 let mut rng = InnerShake256Context::new();
1052 i_shake256_init(&mut rng);
1053 i_shake256_inject(&mut rng, &*seed);
1054 i_shake256_flip(&mut rng);
1055
1056 let mut hd = InnerShake256Context::new();
1057 let mut nonce = [0u8; 40];
1058 falcon_api::falcon_sign_start(&mut rng, &mut nonce, &mut hd);
1059 domain.inject(&mut hd, message);
1060
1061 let rc = falcon_api::falcon_sign_tree_finish(
1062 &mut rng,
1063 &mut sig,
1064 &mut sig_len,
1065 falcon_api::FALCON_SIG_CT,
1066 &self.expanded,
1067 &mut hd,
1068 &nonce,
1069 &mut tmp,
1070 );
1071 if rc != 0 {
1072 return Err(translate_error(rc));
1073 }
1074 sig.truncate(sig_len);
1075 Ok(FnDsaSignature { data: sig })
1076 }
1077
1078 pub fn sign_deterministic(
1080 &self,
1081 message: &[u8],
1082 sign_seed: &[u8],
1083 domain: &DomainSeparation<'_>,
1084 ) -> Result<FnDsaSignature, FalconError> {
1085 domain.validate()?;
1086 let logn = self.logn;
1087 let sig_max = falcon_api::falcon_sig_ct_size(logn);
1088 let tmp_len = falcon_api::falcon_tmpsize_signtree(logn);
1089 let mut sig = vec![0u8; sig_max];
1090 let mut sig_len = sig_max;
1091 let mut tmp = Zeroizing::new(vec![0u8; tmp_len]);
1092
1093 let mut rng = InnerShake256Context::new();
1094 i_shake256_init(&mut rng);
1095 i_shake256_inject(&mut rng, sign_seed);
1096 i_shake256_flip(&mut rng);
1097
1098 let mut hd = InnerShake256Context::new();
1099 let mut nonce = [0u8; 40];
1100 falcon_api::falcon_sign_start(&mut rng, &mut nonce, &mut hd);
1101 domain.inject(&mut hd, message);
1102
1103 let rc = falcon_api::falcon_sign_tree_finish(
1104 &mut rng,
1105 &mut sig,
1106 &mut sig_len,
1107 falcon_api::FALCON_SIG_CT,
1108 &self.expanded,
1109 &mut hd,
1110 &nonce,
1111 &mut tmp,
1112 );
1113 if rc != 0 {
1114 return Err(translate_error(rc));
1115 }
1116 sig.truncate(sig_len);
1117 Ok(FnDsaSignature { data: sig })
1118 }
1119
1120 pub fn public_key(&self) -> &[u8] {
1122 &self.pubkey
1123 }
1124
1125 pub fn logn(&self) -> u32 {
1127 self.logn
1128 }
1129}