#![warn(missing_docs)]
#![allow(clippy::just_underscores_and_digits)]
pub mod c_abi;
pub mod curves;
use core::iter::{once, repeat_n};
use crate::pac::Mclk;
use c_abi::{CryptoRamSlice, Service, u2, u4};
use curves::Curve;
use rand_core::CryptoRng;
macro_rules! copy_to_cryptoram {
(
$crypto_ram:expr,
$(
($name:ident, $data:expr)
),+
) =>
{
{
(&[])
.iter()
.cloned()
$(
.chain($data)
)+
.zip($crypto_ram.iter_mut())
.for_each(|(data_iter, cr_iter)| *cr_iter = data_iter);
let mut _offset = 0;
$(
let len = $data.size_hint().1.unwrap_or_else(|| panic!("provided iterator has no size hint"));
$name = &$crypto_ram[_offset.._offset + len];
_offset += len;
)+
}
}
}
pub struct Pukcc {
__: (),
}
impl Pukcc {
pub fn enable(mclk: &mut Mclk) -> Result<Self, SelfTestFailure> {
unsafe {
c_abi::wait_for_crypto_ram_clear_process();
}
mclk.ahbmask().modify(|_, w| w.pukcc_().set_bit());
let pukcc = Self { __: () };
pukcc.self_test().map(|_| pukcc)
}
pub fn self_test(&self) -> Result<(), SelfTestFailure> {
const PUKCL_VERSION: u4 = 0x04070100;
const CHECKNUM_1: u4 = 0x6E70DDD2;
const CHECKNUM_2: u4 = 0x25C8D64F;
let mut pukcl_params = c_abi::PukclParams::default();
unsafe {
c_abi::SelfTest::call(&mut pukcl_params);
}
let header = pukcl_params.header;
let service_params = unsafe { pukcl_params.params.SelfTest };
match header.u2Status.into() {
PukclReturnCode::Ok => {}
_ => return Err(SelfTestFailure(service_params)),
};
if service_params.u4Version != PUKCL_VERSION {
return Err(SelfTestFailure(service_params));
}
if service_params.u4CheckNum1 != CHECKNUM_1 {
return Err(SelfTestFailure(service_params));
}
if service_params.u4CheckNum2 != CHECKNUM_2 {
return Err(SelfTestFailure(service_params));
}
Ok(())
}
pub fn zp_ecdsa_sign_with_entropy<C: Curve>(
&self,
signature: &mut [u8],
hash: &[u8],
private_key: &[u8],
k_buffer: &mut [u8],
k_entropy_source: &mut impl CryptoRng,
) -> Result<(), EcdsaSignFailure> {
k_entropy_source.fill_bytes(k_buffer);
self.zp_ecdsa_sign::<C>(signature, hash, private_key, k_buffer)
}
pub unsafe fn zp_ecdsa_sign_with_raw_k<C: Curve>(
&self,
signature: &mut [u8],
hash: &[u8],
private_key: &[u8],
k: &[u8],
) -> Result<(), EcdsaSignFailure> {
self.zp_ecdsa_sign::<C>(signature, hash, private_key, k)
}
fn zp_ecdsa_sign<C: Curve>(
&self,
signature: &mut [u8],
hash: &[u8],
private_key: &[u8],
k: &[u8],
) -> Result<(), EcdsaSignFailure> {
C::verify_curve().map_err(EcdsaSignFailure::InvalidCurve)?;
if signature.len() != (2 * C::MOD_LENGTH).into() {
return Err(EcdsaSignFailure::WrongInputParameterLength {
faulty_slice: "signature",
expected_length: (2 * C::MOD_LENGTH).into(),
actual_length: signature.len(),
});
}
if hash.len() != (C::SCALAR_LENGTH).into() {
return Err(EcdsaSignFailure::WrongInputParameterLength {
faulty_slice: "hash",
expected_length: (C::SCALAR_LENGTH).into(),
actual_length: hash.len(),
});
}
if private_key.len() != (C::SCALAR_LENGTH).into() {
return Err(EcdsaSignFailure::WrongInputParameterLength {
faulty_slice: "private_key",
expected_length: (C::SCALAR_LENGTH).into(),
actual_length: private_key.len(),
});
}
if k.len() != (C::SCALAR_LENGTH).into() {
return Err(EcdsaSignFailure::WrongInputParameterLength {
faulty_slice: "k",
expected_length: (C::SCALAR_LENGTH).into(),
actual_length: k.len(),
});
}
let (
modulo_p,
a_curve,
base_point_a_x,
base_point_a_y,
base_point_a_z,
order_point,
cns,
hash_cr,
private_key_cr,
k_cr,
workspace,
mut __,
);
let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
copy_to_cryptoram! {
crypto_ram,
(modulo_p, C::MODULO_P.iter().cloned().rev()),
(a_curve, C::A_CURVE.iter().cloned().rev()),
(base_point_a_x, C::BASE_POINT_A_X.iter().cloned().rev()),
(base_point_a_y, C::BASE_POINT_A_Y.iter().cloned().rev()),
(base_point_a_z, C::BASE_POINT_A_Z.iter().cloned().rev()),
(order_point, C::ORDER_POINT.iter().cloned().rev()),
(cns, C::CNS.iter().cloned().rev()),
(hash_cr, hash.iter().cloned().rev()),
(__, repeat_n(0, 4)),
(private_key_cr, private_key.iter().cloned().rev()),
(__, repeat_n(0, 4)),
(k_cr, k.iter().cloned().rev()),
(__, repeat_n(0, 4)),
(workspace, 0..0)
};
let mut pukcl_params = c_abi::PukclParams::default();
unsafe {
let service_params = &mut pukcl_params.params.ZpEcDsaGenerateFast;
service_params.nu1ModBase = modulo_p.pukcc_base();
service_params.nu1CnsBase = cns.pukcc_base();
service_params.u2ModLength = C::MOD_LENGTH;
service_params.nu1ScalarNumber = k_cr.pukcc_base();
service_params.nu1OrderPointBase = order_point.pukcc_base();
service_params.nu1PrivateKey = private_key_cr.pukcc_base();
service_params.nu1HashBase = hash_cr.pukcc_base();
service_params.u2ScalarLength = C::SCALAR_LENGTH;
service_params.nu1PointABase = base_point_a_x.pukcc_base();
service_params.nu1ABase = a_curve.pukcc_base();
service_params.nu1Workspace = workspace.pukcc_base();
}
unsafe { c_abi::ZpEcDsaGenerateFast::call(&mut pukcl_params) };
match pukcl_params.header.u2Status.into() {
PukclReturnCode::Ok => {}
error_code => return Err(EcdsaSignFailure::ServiceFailure(error_code)),
};
if !base_point_a_z.iter().all(|&el| el == 0) {
return Err(EcdsaSignFailure::BasePointZCoordinateIsNotZero);
}
signature
.iter_mut()
.zip(
base_point_a_x
.iter()
.rev()
.skip(4)
.chain(base_point_a_y.iter().rev().skip(4)),
)
.for_each(|(target_iter, source_iter)| *target_iter = *source_iter);
Ok(())
}
pub fn zp_ecdsa_verify_signature<C: Curve>(
&self,
signature: &[u8],
hash: &[u8],
public_key: &[u8],
) -> Result<(), EcdsaSignatureVerificationFailure> {
C::verify_curve().map_err(EcdsaSignatureVerificationFailure::InvalidCurve)?;
let (
modulo_p,
a_curve,
base_point_a_x,
order_point,
cns,
signature_cr,
hash_cr,
public_key_cr,
workspace,
mut __,
);
if signature.len() != (2 * C::SCALAR_LENGTH).into() {
return Err(
EcdsaSignatureVerificationFailure::WrongInputParameterLength {
faulty_slice: "signature",
expected_length: (2 * C::SCALAR_LENGTH).into(),
actual_length: signature.len(),
},
);
}
if hash.len() != (C::SCALAR_LENGTH).into() {
return Err(
EcdsaSignatureVerificationFailure::WrongInputParameterLength {
faulty_slice: "hash",
expected_length: (C::SCALAR_LENGTH).into(),
actual_length: hash.len(),
},
);
}
if public_key.len() != (2 * C::MOD_LENGTH).into() {
return Err(
EcdsaSignatureVerificationFailure::WrongInputParameterLength {
faulty_slice: "public_key",
expected_length: (2 * C::MOD_LENGTH).into(),
actual_length: public_key.len(),
},
);
}
let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
copy_to_cryptoram! {
crypto_ram,
(modulo_p, C::MODULO_P.iter().cloned().rev()),
(a_curve, C::A_CURVE.iter().cloned().rev()),
(base_point_a_x, C::BASE_POINT_A_X.iter().cloned().rev()),
(__, C::BASE_POINT_A_Y.iter().cloned().rev()),
(__, C::BASE_POINT_A_Z.iter().cloned().rev()),
(order_point, C::ORDER_POINT.iter().cloned().rev()),
(cns, C::CNS.iter().cloned().rev()),
(signature_cr, signature.iter().cloned().take(C::SCALAR_LENGTH.into()).rev()),
(__, repeat_n(0, 4)),
(__, signature.iter().cloned().skip(C::SCALAR_LENGTH.into()).take(C::SCALAR_LENGTH.into()).rev()),
(__, repeat_n(0, 4)),
(hash_cr, hash.iter().cloned().rev()),
(__, repeat_n(0, 4)),
(public_key_cr, public_key.iter().cloned().take(C::MOD_LENGTH.into()).rev()),
(__, repeat_n(0, 4)),
(__, public_key.iter().cloned().skip(C::MOD_LENGTH.into()).take(C::MOD_LENGTH.into()).rev()),
(__, repeat_n(0, 4)),
(__, once(1).chain(repeat_n(0, (C::MOD_LENGTH - 1).into()))),
(__, repeat_n(0, 4)),
(workspace, 0..0)
};
let mut pukcl_params = c_abi::PukclParams::default();
unsafe {
let service_params = &mut pukcl_params.params.ZpEcDsaVerifyFast;
service_params.nu1ModBase = modulo_p.pukcc_base();
service_params.nu1CnsBase = cns.pukcc_base();
service_params.u2ModLength = C::MOD_LENGTH;
service_params.nu1OrderPointBase = order_point.pukcc_base();
service_params.nu1PointSignature = signature_cr.pukcc_base();
service_params.nu1HashBase = hash_cr.pukcc_base();
service_params.u2ScalarLength = C::SCALAR_LENGTH;
service_params.nu1PointABase = base_point_a_x.pukcc_base();
service_params.nu1PointPublicKeyGen = public_key_cr.pukcc_base();
service_params.nu1ABase = a_curve.pukcc_base();
service_params.nu1Workspace = workspace.pukcc_base();
}
unsafe { c_abi::ZpEcDsaVerifyFast::call(&mut pukcl_params) };
match pukcl_params.header.u2Status.into() {
PukclReturnCode::Ok => Ok(()),
error_code => Err(EcdsaSignatureVerificationFailure::ServiceFailure(
error_code,
)),
}
}
pub fn modular_exponentiation<'a>(
&self,
input: &[u8],
exponent: &[u8],
modulus: &[u8],
mode: ExpModMode,
window_size: ExpModWindowSize,
buffer: &'a mut [u8],
) -> Result<&'a [u8], ExpModFailure> {
const PUKCL_EXPMOD_EXPINPUKCCRAM: u16 = 0x02;
if modulus.len() % 4 != 0 {
return Err(ExpModFailure::WrongInputParameterAlignment {
faulty_slice: "modulus",
});
}
const MINIMUM_MODULUS_LEN: usize = 12;
if modulus.len() < MINIMUM_MODULUS_LEN {
return Err(ExpModFailure::WrongInputParameterLength {
faulty_slice: "modulus",
actual_length: modulus.len(),
expected_length: ExpectedLengthError::AtLeast(MINIMUM_MODULUS_LEN),
});
}
if input.len() > modulus.len() {
return Err(ExpModFailure::WrongInputParameterLength {
faulty_slice: "input",
actual_length: input.len(),
expected_length: ExpectedLengthError::AtMost(modulus.len()),
});
}
if exponent.len() > modulus.len() {
return Err(ExpModFailure::WrongInputParameterLength {
faulty_slice: "exponent",
actual_length: exponent.len(),
expected_length: ExpectedLengthError::AtMost(modulus.len()),
});
}
let (modulus_cr, cns_cr, output, workspace, exponent_cr, mut __);
let cns = self.zp_calculate_cns(buffer, modulus)?;
let padding_for_cns = padding_for_len(cns.len());
assert!(cns.len() + padding_for_cns == modulus.len() + 8);
let padding_for_exponent = padding_for_len(exponent.len());
let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
copy_to_cryptoram! {
crypto_ram,
(modulus_cr, modulus.iter().cloned().rev()),
(__, repeat_n(0, 4)),
(cns_cr, cns.iter().cloned().rev()),
(__, repeat_n(0, padding_for_cns)),
(output, input.iter().cloned().rev().chain(repeat_n(0, modulus.len() - input.len()))),
(__, repeat_n(0, 16)),
(exponent_cr, repeat_n(0, 4)),
(__, exponent.iter().cloned().rev()),
(__, repeat_n(0, padding_for_exponent)),
(workspace, 0..0)
};
let workspace_len: usize = match window_size {
ExpModWindowSize::One => 3 * (modulus.len() + 4) + 8,
ExpModWindowSize::Two => 4 * (modulus.len() + 4) + 8,
ExpModWindowSize::Three => 6 * (modulus.len() + 4) + 8,
ExpModWindowSize::Four => 10 * (modulus.len() + 4) + 8,
};
let workspace_end_ptr = workspace.as_ptr().wrapping_add(workspace_len);
let crypto_ram_end_ptr = crypto_ram.as_ptr_range().end;
if workspace_end_ptr > crypto_ram_end_ptr {
return Err(ExpModFailure::RunOutOfCryptoRam {
workspace_end_ptr,
crypto_ram_end_ptr,
});
}
let mut pukcl_params = c_abi::PukclParams::default();
unsafe {
pukcl_params.header.u2Option = PUKCL_EXPMOD_EXPINPUKCCRAM
| window_size.get_windows_size_mask()
| mode.get_mode_mask();
let service_params = &mut pukcl_params.params.ExpMod;
service_params.nu1XBase = output.pukcc_base();
service_params.nu1ModBase = modulus_cr.pukcc_base();
service_params.nu1CnsBase = cns_cr.pukcc_base();
service_params.nu1PrecompBase = workspace.pukcc_base();
service_params.pfu1ExpBase = exponent_cr.as_ptr() as _;
service_params.u2ModLength = modulus.len() as _;
service_params.u2ExpLength = (exponent.len() + padding_for_exponent) as _;
service_params.u1Blinding = 0;
}
unsafe { c_abi::ExpMod::call(&mut pukcl_params) };
match pukcl_params.header.u2Status.into() {
PukclReturnCode::Ok => {}
error_code => return Err(ExpModFailure::ServiceFailure(error_code)),
}
buffer
.iter_mut()
.zip(output.iter().rev())
.for_each(|(target_iter, source_iter)| *target_iter = *source_iter);
Ok(&buffer[..modulus.len()])
}
fn zp_calculate_cns<'a>(
&self,
buffer: &'a mut [u8],
modulus: &[u8],
) -> Result<&'a [u8], CalculateCnsFailure> {
const PUKCL_REDMOD_SETUP: u16 = 0x0100;
if modulus.len() % 4 != 0 {
return Err(CalculateCnsFailure::WrongInputParameterAlignment {
faulty_slice: "modulus",
});
}
let cns_length = modulus.len() + 12;
let actual_cns_length = modulus.len() + 5;
if buffer.len() < actual_cns_length {
return Err(CalculateCnsFailure::WrongInputParameterLength {
faulty_slice: "buffer",
actual_length: buffer.len(),
expected_length: ExpectedLengthError::AtLeast(actual_cns_length),
});
}
let (modulus_cr, cns_cr, workspace_r, workspace_x, mut __);
let mut crypto_ram = unsafe { c_abi::CryptoRam::new() };
copy_to_cryptoram! {
crypto_ram,
(modulus_cr, modulus.iter().cloned().rev()),
(__, repeat_n(0, 4)),
(cns_cr, repeat_n(0, actual_cns_length)),
(__, repeat_n(0, cns_length - actual_cns_length)),
(workspace_r, repeat_n(0, 64)),
(workspace_x, 0..0)
};
let mut pukcl_params = c_abi::PukclParams::default();
unsafe {
pukcl_params.header.u2Option = PUKCL_REDMOD_SETUP;
let service_params = &mut pukcl_params.params.RedMod;
service_params.nu1ModBase = modulus_cr.pukcc_base();
service_params.nu1CnsBase = cns_cr.pukcc_base();
service_params.u2ModLength = modulus.len() as _;
service_params.nu1RBase = workspace_r.pukcc_base();
service_params.nu1XBase = workspace_x.pukcc_base();
}
unsafe { c_abi::RedMod::call(&mut pukcl_params) };
match pukcl_params.header.u2Status.into() {
PukclReturnCode::Ok => {}
error_code => return Err(CalculateCnsFailure::ServiceFailure(error_code)),
}
buffer
.iter_mut()
.zip(cns_cr.iter().rev())
.for_each(|(target_iter, source_iter)| *target_iter = *source_iter);
Ok(&buffer[..actual_cns_length])
}
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct SelfTestFailure(c_abi::SelfTest);
#[allow(missing_docs)]
#[derive(Debug)]
pub enum EcdsaSignFailure {
WrongInputParameterLength {
faulty_slice: &'static str,
expected_length: usize,
actual_length: usize,
},
InvalidCurve(curves::CurveVerificationFailure),
BasePointZCoordinateIsNotZero,
ServiceFailure(PukclReturnCode),
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum EcdsaSignatureVerificationFailure {
WrongInputParameterLength {
faulty_slice: &'static str,
expected_length: usize,
actual_length: usize,
},
InvalidCurve(curves::CurveVerificationFailure),
ServiceFailure(PukclReturnCode),
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum ExpectedLengthError {
AtMost(usize),
AtLeast(usize),
Exactly(usize),
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum ExpModMode {
Regular,
Fast,
}
impl ExpModMode {
pub fn get_mode_mask(&self) -> u2 {
use ExpModMode::*;
match self {
Regular => 0x01,
Fast => 0x04,
}
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum ExpModWindowSize {
One,
Two,
Three,
Four,
}
impl ExpModWindowSize {
pub fn get_windows_size_mask(&self) -> u2 {
use ExpModWindowSize::*;
match self {
One => 0x00,
Two => 0x08,
Three => 0x10,
Four => 0x18,
}
}
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum ExpModFailure {
WrongInputParameterLength {
faulty_slice: &'static str,
expected_length: ExpectedLengthError,
actual_length: usize,
},
WrongInputParameterAlignment {
faulty_slice: &'static str,
},
RunOutOfCryptoRam {
workspace_end_ptr: *const u8,
crypto_ram_end_ptr: *const u8,
},
CalculateCnsFailure(CalculateCnsFailure),
ServiceFailure(PukclReturnCode),
}
#[allow(missing_docs)]
#[derive(Debug)]
pub enum CalculateCnsFailure {
WrongInputParameterLength {
faulty_slice: &'static str,
expected_length: ExpectedLengthError,
actual_length: usize,
},
WrongInputParameterAlignment {
faulty_slice: &'static str,
},
ServiceFailure(PukclReturnCode),
}
impl From<CalculateCnsFailure> for ExpModFailure {
fn from(f: CalculateCnsFailure) -> Self {
ExpModFailure::CalculateCnsFailure(f)
}
}
impl core::convert::From<c_abi::PukclReturnCode> for PukclReturnCode {
fn from(v: c_abi::PukclReturnCode) -> Self {
use PukclReturnCode::*;
match v.0 {
0x0000 => Ok,
0xC001 => Severe(PukclReturnCodeSevere::ComputationNotStarted),
0xC002 => Severe(PukclReturnCodeSevere::UnknownService),
0xC003 => Severe(PukclReturnCodeSevere::UnexploitableOptions),
0xC004 => Severe(PukclReturnCodeSevere::HardwareIssue),
0xC005 => Severe(PukclReturnCodeSevere::WrongHardware),
0xC006 => Severe(PukclReturnCodeSevere::LibraryMalformed),
0xC007 => Severe(PukclReturnCodeSevere::Error),
0xC008 => Severe(PukclReturnCodeSevere::UnknownSubservice),
0xC010 => Severe(PukclReturnCodeSevere::OverlapNotAllowed),
0xC011 => Severe(PukclReturnCodeSevere::ParamNotInPukccram),
0xC012 => Severe(PukclReturnCodeSevere::ParamNotInRam),
0xC013 => Severe(PukclReturnCodeSevere::ParamNotInCpuram),
0xC014 => Severe(PukclReturnCodeSevere::ParamWrongLength),
0xC015 => Severe(PukclReturnCodeSevere::ParamBadAlignment),
0xC016 => Severe(PukclReturnCodeSevere::ParamXBiggerThanY),
0xC017 => Severe(PukclReturnCodeSevere::ParamLengthTooSmall),
0xC101 => Severe(PukclReturnCodeSevere::DivisionByZero),
0xC102 => Severe(PukclReturnCodeSevere::MalformedModulus),
0xC103 => Severe(PukclReturnCodeSevere::FaultDetected),
0xC104 => Severe(PukclReturnCodeSevere::MalformedKey),
0xC105 => Severe(PukclReturnCodeSevere::AprioriOk),
0xC106 => Severe(PukclReturnCodeSevere::WrongService),
0x8001 => Warning(PukclReturnCodeWarning::PointAtInfinity),
0x8002 => Warning(PukclReturnCodeWarning::WrongSignature),
0x8003 => Warning(PukclReturnCodeWarning::WrongSelectnumber),
0x8004 => Warning(PukclReturnCodeWarning::PointIsNotOnCurve),
0x4001 => Info(PukclReturnCodeInfo::NumberIsNotPrime),
0x4002 => Info(PukclReturnCodeInfo::NumberIsPrime),
code => Unknown { code },
}
}
}
impl core::convert::From<PukclReturnCode> for c_abi::PukclReturnCode {
fn from(v: PukclReturnCode) -> Self {
use PukclReturnCode::*;
Self(match v {
Ok => 0x0000,
Severe(PukclReturnCodeSevere::ComputationNotStarted) => 0xC001,
Severe(PukclReturnCodeSevere::UnknownService) => 0xC002,
Severe(PukclReturnCodeSevere::UnexploitableOptions) => 0xC003,
Severe(PukclReturnCodeSevere::HardwareIssue) => 0xC004,
Severe(PukclReturnCodeSevere::WrongHardware) => 0xC005,
Severe(PukclReturnCodeSevere::LibraryMalformed) => 0xC006,
Severe(PukclReturnCodeSevere::Error) => 0xC007,
Severe(PukclReturnCodeSevere::UnknownSubservice) => 0xC008,
Severe(PukclReturnCodeSevere::OverlapNotAllowed) => 0xC010,
Severe(PukclReturnCodeSevere::ParamNotInPukccram) => 0xC011,
Severe(PukclReturnCodeSevere::ParamNotInRam) => 0xC012,
Severe(PukclReturnCodeSevere::ParamNotInCpuram) => 0xC013,
Severe(PukclReturnCodeSevere::ParamWrongLength) => 0xC014,
Severe(PukclReturnCodeSevere::ParamBadAlignment) => 0xC015,
Severe(PukclReturnCodeSevere::ParamXBiggerThanY) => 0xC016,
Severe(PukclReturnCodeSevere::ParamLengthTooSmall) => 0xC017,
Severe(PukclReturnCodeSevere::DivisionByZero) => 0xC101,
Severe(PukclReturnCodeSevere::MalformedModulus) => 0xC102,
Severe(PukclReturnCodeSevere::FaultDetected) => 0xC103,
Severe(PukclReturnCodeSevere::MalformedKey) => 0xC104,
Severe(PukclReturnCodeSevere::AprioriOk) => 0xC105,
Severe(PukclReturnCodeSevere::WrongService) => 0xC106,
Warning(PukclReturnCodeWarning::PointAtInfinity) => 0x8001,
Warning(PukclReturnCodeWarning::WrongSignature) => 0x8002,
Warning(PukclReturnCodeWarning::WrongSelectnumber) => 0x8003,
Warning(PukclReturnCodeWarning::PointIsNotOnCurve) => 0x8004,
Info(PukclReturnCodeInfo::NumberIsNotPrime) => 0x4001,
Info(PukclReturnCodeInfo::NumberIsPrime) => 0x4002,
Unknown { code } => code,
})
}
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum PukclReturnCode {
Ok,
Info(PukclReturnCodeInfo),
Warning(PukclReturnCodeWarning),
Severe(PukclReturnCodeSevere),
Unknown { code: u16 },
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum PukclReturnCodeInfo {
NumberIsNotPrime,
NumberIsPrime,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum PukclReturnCodeWarning {
PointAtInfinity,
WrongSignature,
WrongSelectnumber,
PointIsNotOnCurve,
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum PukclReturnCodeSevere {
ComputationNotStarted,
UnknownService,
UnexploitableOptions,
HardwareIssue,
WrongHardware,
LibraryMalformed,
Error,
UnknownSubservice,
OverlapNotAllowed,
ParamNotInPukccram,
ParamNotInRam,
ParamNotInCpuram,
ParamWrongLength,
ParamBadAlignment,
ParamXBiggerThanY,
ParamLengthTooSmall,
DivisionByZero,
MalformedModulus,
FaultDetected,
MalformedKey,
AprioriOk,
WrongService,
}
fn padding_for_len(len: usize) -> usize {
const ALIGNMENT: usize = 4;
if len % ALIGNMENT != 0 {
ALIGNMENT - (len % ALIGNMENT)
} else {
0
}
}