1#![warn(missing_docs)]
2#![allow(clippy::just_underscores_and_digits)]
21pub mod c_abi;
22pub mod curves;
23
24use core::iter::{once, repeat};
25
26use crate::pac::Mclk;
27use c_abi::{u2, u4, CryptoRamSlice, Service};
28use curves::Curve;
29
30use rand_core::{CryptoRng, RngCore};
31
32macro_rules! copy_to_cryptoram {
35 (
36 $crypto_ram:expr,
37 $(
38 ($name:ident, $data:expr)
39 ),+
40 ) =>
41 {
42 {
43 (&[])
44 .iter()
45 .cloned()
46 $(
47 .chain($data)
48 )+
49 .zip($crypto_ram.iter_mut())
50 .for_each(|(data_iter, cr_iter)| *cr_iter = data_iter);
51
52 let mut _offset = 0;
53 $(
54 let len = $data.size_hint().1.unwrap_or_else(|| panic!("provided iterator has no size hint"));
55 $name = &$crypto_ram[_offset.._offset + len];
56 _offset += len;
57 )+
58 }
59 }
60}
61
62pub struct Pukcc {
67 __: (),
68}
69
70impl Pukcc {
71 pub fn enable(mclk: &mut Mclk) -> Result<Self, SelfTestFailure> {
76 unsafe {
77 c_abi::wait_for_crypto_ram_clear_process();
78 }
79 mclk.ahbmask().modify(|_, w| w.pukcc_().set_bit());
80 let pukcc = Self { __: () };
81 pukcc.self_test().map(|_| pukcc)
82 }
83
84 pub fn self_test(&self) -> Result<(), SelfTestFailure> {
93 const PUKCL_VERSION: u4 = 0x04070100;
94 const CHECKNUM_1: u4 = 0x6E70DDD2;
95 const CHECKNUM_2: u4 = 0x25C8D64F;
96 let mut pukcl_params = c_abi::PukclParams::default();
97 unsafe {
98 c_abi::SelfTest::call(&mut pukcl_params);
99 }
100 let header = pukcl_params.header;
101 let service_params = unsafe { pukcl_params.params.SelfTest };
102 match header.u2Status.into() {
103 PukclReturnCode::Ok => {}
104 _ => return Err(SelfTestFailure(service_params)),
105 };
106 if service_params.u4Version != PUKCL_VERSION {
107 return Err(SelfTestFailure(service_params));
108 }
109 if service_params.u4CheckNum1 != CHECKNUM_1 {
110 return Err(SelfTestFailure(service_params));
111 }
112 if service_params.u4CheckNum2 != CHECKNUM_2 {
113 return Err(SelfTestFailure(service_params));
114 }
115
116 Ok(())
117 }
118
119 pub fn zp_ecdsa_sign_with_entropy<C: Curve>(
154 &self,
155 signature: &mut [u8],
156 hash: &[u8],
157 private_key: &[u8],
158 k_buffer: &mut [u8],
159 k_entropy_source: &mut (impl RngCore + CryptoRng),
160 ) -> Result<(), EcdsaSignFailure> {
161 k_entropy_source.fill_bytes(k_buffer);
162 self.zp_ecdsa_sign::<C>(signature, hash, private_key, k_buffer)
163 }
164
165 pub unsafe fn zp_ecdsa_sign_with_raw_k<C: Curve>(
208 &self,
209 signature: &mut [u8],
210 hash: &[u8],
211 private_key: &[u8],
212 k: &[u8],
213 ) -> Result<(), EcdsaSignFailure> {
214 self.zp_ecdsa_sign::<C>(signature, hash, private_key, k)
215 }
216
217 fn zp_ecdsa_sign<C: Curve>(
218 &self,
219 signature: &mut [u8],
220 hash: &[u8],
221 private_key: &[u8],
222 k: &[u8],
223 ) -> Result<(), EcdsaSignFailure> {
224 C::verify_curve().map_err(EcdsaSignFailure::InvalidCurve)?;
225
226 if signature.len() != (2 * C::MOD_LENGTH).into() {
227 return Err(EcdsaSignFailure::WrongInputParameterLength {
228 faulty_slice: "signature",
229 expected_length: (2 * C::MOD_LENGTH).into(),
230 actual_length: signature.len(),
231 });
232 }
233 if hash.len() != (C::SCALAR_LENGTH).into() {
234 return Err(EcdsaSignFailure::WrongInputParameterLength {
235 faulty_slice: "hash",
236 expected_length: (C::SCALAR_LENGTH).into(),
237 actual_length: hash.len(),
238 });
239 }
240 if private_key.len() != (C::SCALAR_LENGTH).into() {
241 return Err(EcdsaSignFailure::WrongInputParameterLength {
242 faulty_slice: "private_key",
243 expected_length: (C::SCALAR_LENGTH).into(),
244 actual_length: private_key.len(),
245 });
246 }
247 if k.len() != (C::SCALAR_LENGTH).into() {
248 return Err(EcdsaSignFailure::WrongInputParameterLength {
249 faulty_slice: "k",
250 expected_length: (C::SCALAR_LENGTH).into(),
251 actual_length: k.len(),
252 });
253 }
254 let (
255 modulo_p,
256 a_curve,
257 base_point_a_x,
258 base_point_a_y,
259 base_point_a_z,
260 order_point,
261 cns,
262 hash_cr,
263 private_key_cr,
264 k_cr,
265 workspace,
266 mut __,
267 );
268 let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
269 copy_to_cryptoram! {
276 crypto_ram,
277 (modulo_p, C::MODULO_P.iter().cloned().rev()),
278 (a_curve, C::A_CURVE.iter().cloned().rev()),
279 (base_point_a_x, C::BASE_POINT_A_X.iter().cloned().rev()),
280 (base_point_a_y, C::BASE_POINT_A_Y.iter().cloned().rev()),
281 (base_point_a_z, C::BASE_POINT_A_Z.iter().cloned().rev()),
282 (order_point, C::ORDER_POINT.iter().cloned().rev()),
283 (cns, C::CNS.iter().cloned().rev()),
284 (hash_cr, hash.iter().cloned().rev()),
285 (__, repeat(0).take(4)),
286 (private_key_cr, private_key.iter().cloned().rev()),
287 (__, repeat(0).take(4)),
288 (k_cr, k.iter().cloned().rev()),
289 (__, repeat(0).take(4)),
290 (workspace, 0..0)
294 };
295 let mut pukcl_params = c_abi::PukclParams::default();
296 unsafe {
297 let service_params = &mut pukcl_params.params.ZpEcDsaGenerateFast;
298 service_params.nu1ModBase = modulo_p.pukcc_base();
299 service_params.nu1CnsBase = cns.pukcc_base();
300 service_params.u2ModLength = C::MOD_LENGTH;
301 service_params.nu1ScalarNumber = k_cr.pukcc_base();
302 service_params.nu1OrderPointBase = order_point.pukcc_base();
303 service_params.nu1PrivateKey = private_key_cr.pukcc_base();
304 service_params.nu1HashBase = hash_cr.pukcc_base();
305 service_params.u2ScalarLength = C::SCALAR_LENGTH;
306 service_params.nu1PointABase = base_point_a_x.pukcc_base();
307 service_params.nu1ABase = a_curve.pukcc_base();
308 service_params.nu1Workspace = workspace.pukcc_base();
309 }
310
311 unsafe { c_abi::ZpEcDsaGenerateFast::call(&mut pukcl_params) };
312
313 match pukcl_params.header.u2Status.into() {
314 PukclReturnCode::Ok => {}
315 error_code => return Err(EcdsaSignFailure::ServiceFailure(error_code)),
316 };
317
318 if !base_point_a_z.iter().all(|&el| el == 0) {
323 return Err(EcdsaSignFailure::BasePointZCoordinateIsNotZero);
324 }
325
326 signature
328 .iter_mut()
329 .zip(
330 base_point_a_x
331 .iter()
332 .rev()
333 .skip(4)
334 .chain(base_point_a_y.iter().rev().skip(4)),
335 )
336 .for_each(|(target_iter, source_iter)| *target_iter = *source_iter);
337
338 Ok(())
339 }
340
341 pub fn zp_ecdsa_verify_signature<C: Curve>(
365 &self,
366 signature: &[u8],
367 hash: &[u8],
368 public_key: &[u8],
369 ) -> Result<(), EcdsaSignatureVerificationFailure> {
370 C::verify_curve().map_err(EcdsaSignatureVerificationFailure::InvalidCurve)?;
371
372 let (
373 modulo_p,
374 a_curve,
375 base_point_a_x,
376 order_point,
377 cns,
378 signature_cr,
379 hash_cr,
380 public_key_cr,
381 workspace,
382 mut __,
383 );
384 if signature.len() != (2 * C::SCALAR_LENGTH).into() {
385 return Err(
386 EcdsaSignatureVerificationFailure::WrongInputParameterLength {
387 faulty_slice: "signature",
388 expected_length: (2 * C::SCALAR_LENGTH).into(),
389 actual_length: signature.len(),
390 },
391 );
392 }
393 if hash.len() != (C::SCALAR_LENGTH).into() {
394 return Err(
395 EcdsaSignatureVerificationFailure::WrongInputParameterLength {
396 faulty_slice: "hash",
397 expected_length: (C::SCALAR_LENGTH).into(),
398 actual_length: hash.len(),
399 },
400 );
401 }
402 if public_key.len() != (2 * C::MOD_LENGTH).into() {
403 return Err(
404 EcdsaSignatureVerificationFailure::WrongInputParameterLength {
405 faulty_slice: "public_key",
406 expected_length: (2 * C::MOD_LENGTH).into(),
407 actual_length: public_key.len(),
408 },
409 );
410 }
411 let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
412 copy_to_cryptoram! {
419 crypto_ram,
420 (modulo_p, C::MODULO_P.iter().cloned().rev()),
421 (a_curve, C::A_CURVE.iter().cloned().rev()),
422 (base_point_a_x, C::BASE_POINT_A_X.iter().cloned().rev()),
423 (__, C::BASE_POINT_A_Y.iter().cloned().rev()),
424 (__, C::BASE_POINT_A_Z.iter().cloned().rev()),
425 (order_point, C::ORDER_POINT.iter().cloned().rev()),
426 (cns, C::CNS.iter().cloned().rev()),
427 (signature_cr, signature.iter().cloned().take(C::SCALAR_LENGTH.into()).rev()),
431 (__, repeat(0).take(4)),
432 (__, signature.iter().cloned().skip(C::SCALAR_LENGTH.into()).take(C::SCALAR_LENGTH.into()).rev()),
434 (__, repeat(0).take(4)),
435 (hash_cr, hash.iter().cloned().rev()),
436 (__, repeat(0).take(4)),
437 (public_key_cr, public_key.iter().cloned().take(C::MOD_LENGTH.into()).rev()),
441 (__, repeat(0).take(4)),
442 (__, public_key.iter().cloned().skip(C::MOD_LENGTH.into()).take(C::MOD_LENGTH.into()).rev()),
444 (__, repeat(0).take(4)),
445 (__, once(1).chain(repeat(0).take((C::MOD_LENGTH - 1).into()))),
447 (__, repeat(0).take(4)),
448 (workspace, 0..0)
452 };
453 let mut pukcl_params = c_abi::PukclParams::default();
454 unsafe {
455 let service_params = &mut pukcl_params.params.ZpEcDsaVerifyFast;
456 service_params.nu1ModBase = modulo_p.pukcc_base();
457 service_params.nu1CnsBase = cns.pukcc_base();
458 service_params.u2ModLength = C::MOD_LENGTH;
459 service_params.nu1OrderPointBase = order_point.pukcc_base();
460 service_params.nu1PointSignature = signature_cr.pukcc_base();
461 service_params.nu1HashBase = hash_cr.pukcc_base();
462 service_params.u2ScalarLength = C::SCALAR_LENGTH;
463 service_params.nu1PointABase = base_point_a_x.pukcc_base();
464 service_params.nu1PointPublicKeyGen = public_key_cr.pukcc_base();
465 service_params.nu1ABase = a_curve.pukcc_base();
466 service_params.nu1Workspace = workspace.pukcc_base();
467 }
468
469 unsafe { c_abi::ZpEcDsaVerifyFast::call(&mut pukcl_params) };
470
471 match pukcl_params.header.u2Status.into() {
472 PukclReturnCode::Ok => Ok(()),
473 error_code => Err(EcdsaSignatureVerificationFailure::ServiceFailure(
474 error_code,
475 )),
476 }
477 }
478
479 pub fn modular_exponentiation<'a>(
567 &self,
568 input: &[u8],
569 exponent: &[u8],
570 modulus: &[u8],
571 mode: ExpModMode,
572 window_size: ExpModWindowSize,
573 buffer: &'a mut [u8],
574 ) -> Result<&'a [u8], ExpModFailure> {
575 const PUKCL_EXPMOD_EXPINPUKCCRAM: u16 = 0x02;
576
577 if modulus.len() % 4 != 0 {
579 return Err(ExpModFailure::WrongInputParameterAlignment {
580 faulty_slice: "modulus",
581 });
582 }
583 const MINIMUM_MODULUS_LEN: usize = 12;
585 if modulus.len() < MINIMUM_MODULUS_LEN {
586 return Err(ExpModFailure::WrongInputParameterLength {
587 faulty_slice: "modulus",
588 actual_length: modulus.len(),
589 expected_length: ExpectedLengthError::AtLeast(MINIMUM_MODULUS_LEN),
590 });
591 }
592 if input.len() > modulus.len() {
596 return Err(ExpModFailure::WrongInputParameterLength {
597 faulty_slice: "input",
598 actual_length: input.len(),
599 expected_length: ExpectedLengthError::AtMost(modulus.len()),
600 });
601 }
602 if exponent.len() > modulus.len() {
606 return Err(ExpModFailure::WrongInputParameterLength {
607 faulty_slice: "exponent",
608 actual_length: exponent.len(),
609 expected_length: ExpectedLengthError::AtMost(modulus.len()),
610 });
611 }
612
613 let (modulus_cr, cns_cr, output, workspace, exponent_cr, mut __);
614
615 let cns = self.zp_calculate_cns(buffer, modulus)?;
616 let padding_for_cns = padding_for_len(cns.len());
617 assert!(cns.len() + padding_for_cns == modulus.len() + 8);
619 let padding_for_exponent = padding_for_len(exponent.len());
620
621 let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
622 copy_to_cryptoram! {
626 crypto_ram,
627 (modulus_cr, modulus.iter().cloned().rev()),
628 (__, repeat(0).take(4)),
629 (cns_cr, cns.iter().cloned().rev()),
630 (__, repeat(0).take(padding_for_cns)),
631 (output, input.iter().cloned().rev().chain(repeat(0).take(modulus.len() - input.len()))),
634 (__, repeat(0).take(16)),
636 (exponent_cr, repeat(0).take(4)),
639 (__, exponent.iter().cloned().rev()),
640 (__, repeat(0).take(padding_for_exponent)),
641 (workspace, 0..0)
645 };
646 let workspace_len: usize = match window_size {
648 ExpModWindowSize::One => 3 * (modulus.len() + 4) + 8,
649 ExpModWindowSize::Two => 4 * (modulus.len() + 4) + 8,
650 ExpModWindowSize::Three => 6 * (modulus.len() + 4) + 8,
651 ExpModWindowSize::Four => 10 * (modulus.len() + 4) + 8,
652 };
653 let workspace_end_ptr = workspace.as_ptr().wrapping_add(workspace_len);
654 let crypto_ram_end_ptr = crypto_ram.as_ptr_range().end;
655 if workspace_end_ptr > crypto_ram_end_ptr {
656 return Err(ExpModFailure::RunOutOfCryptoRam {
657 workspace_end_ptr,
658 crypto_ram_end_ptr,
659 });
660 }
661 let mut pukcl_params = c_abi::PukclParams::default();
662 unsafe {
663 pukcl_params.header.u2Option = PUKCL_EXPMOD_EXPINPUKCCRAM
665 | window_size.get_windows_size_mask()
666 | mode.get_mode_mask();
667 let service_params = &mut pukcl_params.params.ExpMod;
668 service_params.nu1XBase = output.pukcc_base();
669 service_params.nu1ModBase = modulus_cr.pukcc_base();
670 service_params.nu1CnsBase = cns_cr.pukcc_base();
671 service_params.nu1PrecompBase = workspace.pukcc_base();
672 service_params.pfu1ExpBase = exponent_cr.as_ptr() as _;
673 service_params.u2ModLength = modulus.len() as _;
674 service_params.u2ExpLength = (exponent.len() + padding_for_exponent) as _;
675 service_params.u1Blinding = 0;
676 }
677
678 unsafe { c_abi::ExpMod::call(&mut pukcl_params) };
679 match pukcl_params.header.u2Status.into() {
680 PukclReturnCode::Ok => {}
681 error_code => return Err(ExpModFailure::ServiceFailure(error_code)),
682 }
683
684 buffer
685 .iter_mut()
686 .zip(output.iter().rev())
687 .for_each(|(target_iter, source_iter)| *target_iter = *source_iter);
688
689 Ok(&buffer[..modulus.len()])
690 }
691
692 fn zp_calculate_cns<'a>(
694 &self,
695 buffer: &'a mut [u8],
696 modulus: &[u8],
697 ) -> Result<&'a [u8], CalculateCnsFailure> {
698 const PUKCL_REDMOD_SETUP: u16 = 0x0100;
699 if modulus.len() % 4 != 0 {
700 return Err(CalculateCnsFailure::WrongInputParameterAlignment {
701 faulty_slice: "modulus",
702 });
703 }
704
705 let cns_length = modulus.len() + 12;
709 let actual_cns_length = modulus.len() + 5;
710
711 if buffer.len() < actual_cns_length {
712 return Err(CalculateCnsFailure::WrongInputParameterLength {
713 faulty_slice: "buffer",
714 actual_length: buffer.len(),
715 expected_length: ExpectedLengthError::AtLeast(actual_cns_length),
716 });
717 }
718 let (modulus_cr, cns_cr, workspace_r, workspace_x, mut __);
719 let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
720 copy_to_cryptoram! {
721 crypto_ram,
722 (modulus_cr, modulus.iter().cloned().rev()),
723 (__, repeat(0).take(4)),
724 (cns_cr, repeat(0).take(actual_cns_length)),
725 (__, repeat(0).take(cns_length - actual_cns_length)),
726 (workspace_r, repeat(0).take(64)),
728 (workspace_x, 0..0)
729 };
730 let mut pukcl_params = c_abi::PukclParams::default();
731 unsafe {
732 pukcl_params.header.u2Option = PUKCL_REDMOD_SETUP;
734 let service_params = &mut pukcl_params.params.RedMod;
735 service_params.nu1ModBase = modulus_cr.pukcc_base();
736 service_params.nu1CnsBase = cns_cr.pukcc_base();
737 service_params.u2ModLength = modulus.len() as _;
738 service_params.nu1RBase = workspace_r.pukcc_base();
739 service_params.nu1XBase = workspace_x.pukcc_base();
740 }
741 unsafe { c_abi::RedMod::call(&mut pukcl_params) };
742 match pukcl_params.header.u2Status.into() {
743 PukclReturnCode::Ok => {}
744 error_code => return Err(CalculateCnsFailure::ServiceFailure(error_code)),
745 }
746
747 buffer
748 .iter_mut()
749 .zip(cns_cr.iter().rev())
750 .for_each(|(target_iter, source_iter)| *target_iter = *source_iter);
751 Ok(&buffer[..actual_cns_length])
752 }
753}
754
755#[derive(Debug)]
757#[allow(dead_code)]
758pub struct SelfTestFailure(c_abi::SelfTest);
759
760#[allow(missing_docs)]
764#[derive(Debug)]
765pub enum EcdsaSignFailure {
766 WrongInputParameterLength {
767 faulty_slice: &'static str,
768 expected_length: usize,
769 actual_length: usize,
770 },
771 InvalidCurve(curves::CurveVerificationFailure),
772 BasePointZCoordinateIsNotZero,
773 ServiceFailure(PukclReturnCode),
774}
775
776#[allow(missing_docs)]
779#[derive(Debug)]
780pub enum EcdsaSignatureVerificationFailure {
781 WrongInputParameterLength {
782 faulty_slice: &'static str,
783 expected_length: usize,
784 actual_length: usize,
785 },
786 InvalidCurve(curves::CurveVerificationFailure),
787 ServiceFailure(PukclReturnCode),
788}
789
790#[allow(missing_docs)]
792#[derive(Debug)]
793pub enum ExpectedLengthError {
794 AtMost(usize),
795 AtLeast(usize),
796 Exactly(usize),
797}
798
799#[allow(missing_docs)]
802#[derive(Debug)]
803pub enum ExpModMode {
804 Regular,
805 Fast,
806}
807
808impl ExpModMode {
809 pub fn get_mode_mask(&self) -> u2 {
812 use ExpModMode::*;
813 match self {
814 Regular => 0x01,
815 Fast => 0x04,
816 }
817 }
818}
819
820#[allow(missing_docs)]
823#[derive(Debug)]
824pub enum ExpModWindowSize {
825 One,
827 Two,
829 Three,
831 Four,
833}
834
835impl ExpModWindowSize {
836 pub fn get_windows_size_mask(&self) -> u2 {
839 use ExpModWindowSize::*;
840 match self {
841 One => 0x00,
842 Two => 0x08,
843 Three => 0x10,
844 Four => 0x18,
845 }
846 }
847}
848
849#[allow(missing_docs)]
852#[derive(Debug)]
853pub enum ExpModFailure {
854 WrongInputParameterLength {
855 faulty_slice: &'static str,
856 expected_length: ExpectedLengthError,
857 actual_length: usize,
858 },
859 WrongInputParameterAlignment {
861 faulty_slice: &'static str,
862 },
863 RunOutOfCryptoRam {
864 workspace_end_ptr: *const u8,
865 crypto_ram_end_ptr: *const u8,
866 },
867 CalculateCnsFailure(CalculateCnsFailure),
868 ServiceFailure(PukclReturnCode),
869}
870
871#[allow(missing_docs)]
874#[derive(Debug)]
875pub enum CalculateCnsFailure {
876 WrongInputParameterLength {
877 faulty_slice: &'static str,
878 expected_length: ExpectedLengthError,
879 actual_length: usize,
880 },
881 WrongInputParameterAlignment {
883 faulty_slice: &'static str,
884 },
885 ServiceFailure(PukclReturnCode),
886}
887
888impl From<CalculateCnsFailure> for ExpModFailure {
889 fn from(f: CalculateCnsFailure) -> Self {
890 ExpModFailure::CalculateCnsFailure(f)
891 }
892}
893
894impl core::convert::From<c_abi::PukclReturnCode> for PukclReturnCode {
896 fn from(v: c_abi::PukclReturnCode) -> Self {
897 use PukclReturnCode::*;
898 match v.0 {
899 0x0000 => Ok,
900 0xC001 => Severe(PukclReturnCodeSevere::ComputationNotStarted),
901 0xC002 => Severe(PukclReturnCodeSevere::UnknownService),
902 0xC003 => Severe(PukclReturnCodeSevere::UnexploitableOptions),
903 0xC004 => Severe(PukclReturnCodeSevere::HardwareIssue),
904 0xC005 => Severe(PukclReturnCodeSevere::WrongHardware),
905 0xC006 => Severe(PukclReturnCodeSevere::LibraryMalformed),
906 0xC007 => Severe(PukclReturnCodeSevere::Error),
907 0xC008 => Severe(PukclReturnCodeSevere::UnknownSubservice),
908 0xC010 => Severe(PukclReturnCodeSevere::OverlapNotAllowed),
909 0xC011 => Severe(PukclReturnCodeSevere::ParamNotInPukccram),
910 0xC012 => Severe(PukclReturnCodeSevere::ParamNotInRam),
911 0xC013 => Severe(PukclReturnCodeSevere::ParamNotInCpuram),
912 0xC014 => Severe(PukclReturnCodeSevere::ParamWrongLength),
913 0xC015 => Severe(PukclReturnCodeSevere::ParamBadAlignment),
914 0xC016 => Severe(PukclReturnCodeSevere::ParamXBiggerThanY),
915 0xC017 => Severe(PukclReturnCodeSevere::ParamLengthTooSmall),
916 0xC101 => Severe(PukclReturnCodeSevere::DivisionByZero),
917 0xC102 => Severe(PukclReturnCodeSevere::MalformedModulus),
918 0xC103 => Severe(PukclReturnCodeSevere::FaultDetected),
919 0xC104 => Severe(PukclReturnCodeSevere::MalformedKey),
920 0xC105 => Severe(PukclReturnCodeSevere::AprioriOk),
921 0xC106 => Severe(PukclReturnCodeSevere::WrongService),
922 0x8001 => Warning(PukclReturnCodeWarning::PointAtInfinity),
923 0x8002 => Warning(PukclReturnCodeWarning::WrongSignature),
924 0x8003 => Warning(PukclReturnCodeWarning::WrongSelectnumber),
925 0x8004 => Warning(PukclReturnCodeWarning::PointIsNotOnCurve),
926 0x4001 => Info(PukclReturnCodeInfo::NumberIsNotPrime),
927 0x4002 => Info(PukclReturnCodeInfo::NumberIsPrime),
928 code => Unknown { code },
929 }
930 }
931}
932
933impl core::convert::From<PukclReturnCode> for c_abi::PukclReturnCode {
934 fn from(v: PukclReturnCode) -> Self {
935 use PukclReturnCode::*;
936 Self(match v {
937 Ok => 0x0000,
938 Severe(PukclReturnCodeSevere::ComputationNotStarted) => 0xC001,
939 Severe(PukclReturnCodeSevere::UnknownService) => 0xC002,
940 Severe(PukclReturnCodeSevere::UnexploitableOptions) => 0xC003,
941 Severe(PukclReturnCodeSevere::HardwareIssue) => 0xC004,
942 Severe(PukclReturnCodeSevere::WrongHardware) => 0xC005,
943 Severe(PukclReturnCodeSevere::LibraryMalformed) => 0xC006,
944 Severe(PukclReturnCodeSevere::Error) => 0xC007,
945 Severe(PukclReturnCodeSevere::UnknownSubservice) => 0xC008,
946 Severe(PukclReturnCodeSevere::OverlapNotAllowed) => 0xC010,
947 Severe(PukclReturnCodeSevere::ParamNotInPukccram) => 0xC011,
948 Severe(PukclReturnCodeSevere::ParamNotInRam) => 0xC012,
949 Severe(PukclReturnCodeSevere::ParamNotInCpuram) => 0xC013,
950 Severe(PukclReturnCodeSevere::ParamWrongLength) => 0xC014,
951 Severe(PukclReturnCodeSevere::ParamBadAlignment) => 0xC015,
952 Severe(PukclReturnCodeSevere::ParamXBiggerThanY) => 0xC016,
953 Severe(PukclReturnCodeSevere::ParamLengthTooSmall) => 0xC017,
954 Severe(PukclReturnCodeSevere::DivisionByZero) => 0xC101,
955 Severe(PukclReturnCodeSevere::MalformedModulus) => 0xC102,
956 Severe(PukclReturnCodeSevere::FaultDetected) => 0xC103,
957 Severe(PukclReturnCodeSevere::MalformedKey) => 0xC104,
958 Severe(PukclReturnCodeSevere::AprioriOk) => 0xC105,
959 Severe(PukclReturnCodeSevere::WrongService) => 0xC106,
960 Warning(PukclReturnCodeWarning::PointAtInfinity) => 0x8001,
961 Warning(PukclReturnCodeWarning::WrongSignature) => 0x8002,
962 Warning(PukclReturnCodeWarning::WrongSelectnumber) => 0x8003,
963 Warning(PukclReturnCodeWarning::PointIsNotOnCurve) => 0x8004,
964 Info(PukclReturnCodeInfo::NumberIsNotPrime) => 0x4001,
965 Info(PukclReturnCodeInfo::NumberIsPrime) => 0x4002,
966 Unknown { code } => code,
967 })
968 }
969}
970
971#[allow(missing_docs)]
975#[derive(Clone, Copy, Debug)]
976pub enum PukclReturnCode {
977 Ok,
978 Info(PukclReturnCodeInfo),
979 Warning(PukclReturnCodeWarning),
980 Severe(PukclReturnCodeSevere),
981 Unknown { code: u16 },
982}
983
984#[allow(missing_docs)]
986#[derive(Clone, Copy, Debug)]
987pub enum PukclReturnCodeInfo {
988 NumberIsNotPrime,
989 NumberIsPrime,
990}
991
992#[allow(missing_docs)]
994#[derive(Clone, Copy, Debug)]
995pub enum PukclReturnCodeWarning {
996 PointAtInfinity,
997 WrongSignature,
998 WrongSelectnumber,
999 PointIsNotOnCurve,
1000}
1001
1002#[allow(missing_docs)]
1004#[derive(Clone, Copy, Debug)]
1005pub enum PukclReturnCodeSevere {
1006 ComputationNotStarted,
1007 UnknownService,
1008 UnexploitableOptions,
1009 HardwareIssue,
1010 WrongHardware,
1011 LibraryMalformed,
1012 Error,
1013 UnknownSubservice,
1014 OverlapNotAllowed,
1015 ParamNotInPukccram,
1016 ParamNotInRam,
1017 ParamNotInCpuram,
1018 ParamWrongLength,
1019 ParamBadAlignment,
1020 ParamXBiggerThanY,
1021 ParamLengthTooSmall,
1022 DivisionByZero,
1023 MalformedModulus,
1024 FaultDetected,
1025 MalformedKey,
1026 AprioriOk,
1027 WrongService,
1028}
1029
1030fn padding_for_len(len: usize) -> usize {
1031 const ALIGNMENT: usize = 4;
1032 if len % ALIGNMENT != 0 {
1033 ALIGNMENT - (len % ALIGNMENT)
1034 } else {
1035 0
1036 }
1037}