atsamd_hal/peripherals/pukcc/
c_abi.rs

1//! Module that defines low-level constructs required for interaction with
2//! PUKCC
3#![allow(missing_docs)]
4#![allow(non_camel_case_types)]
5#![allow(non_snake_case)]
6
7use bitfield::bitfield;
8
9pub type nu1 = u16;
10pub type u2 = u16;
11pub type u4 = u32;
12pub type pu1 = u32;
13pub type u1 = u8;
14pub type pfu1 = u32;
15
16#[repr(C)]
17#[derive(Copy, Clone, Default, Debug)]
18pub struct Smult {
19    pub nu1ModBase: nu1,
20    pub nu1CnsBase: nu1,
21    pub u2ModLength: u2,
22    pub nu1XBase: nu1,
23    pub u2RLength: u2,
24    pub nu1ZBase: nu1,
25    pub nu1RBase: nu1,
26    pub u2XLength: u2,
27    pub u4MulValue: u4,
28}
29
30#[repr(C)]
31#[derive(Copy, Clone, Default, Debug)]
32pub struct ZpEccAddSubFast {
33    pub nu1ModBase: nu1,
34    pub nu1CnsBase: nu1,
35    pub u2ModLength: u2,
36    pub nu1PointABase: nu1,
37    pub nu1PointBBase: nu1,
38    pub nu1Workspace: nu1,
39    pub __Padding1: nu1,
40    pub u2Operator: u2,
41}
42
43#[repr(C)]
44#[derive(Copy, Clone, Default, Debug)]
45pub struct GF2NEccMulFast {
46    pub nu1PointBase: nu1,
47    pub nu1ModBase: nu1,
48    pub nu1CnsBase: nu1,
49    pub nu1KBase: nu1,
50    pub nu1ABase: nu1,
51    pub nu1Workspace: nu1,
52    pub u2ModLength: u2,
53    pub u2KLength: u2,
54}
55
56#[repr(C)]
57#[derive(Copy, Clone, Default, Debug)]
58pub struct Fill {
59    pub __Padding0: nu1,
60    pub __Padding1: nu1,
61    pub __Padding2: u2,
62    pub __Padding3: u2,
63    pub __Padding4: u2,
64    pub __Padding5: u2,
65    pub nu1RBase: nu1,
66    pub u2RLength: u2,
67    pub u4FillValue: u4,
68}
69
70#[repr(C)]
71#[derive(Copy, Clone, Default, Debug)]
72pub struct RedMod {
73    pub nu1ModBase: nu1,
74    pub nu1CnsBase: nu1,
75    pub u2ModLength: u2,
76    pub nu1RBase: nu1,
77    pub __Padding0: u2,
78    pub __Padding1: u2,
79    pub nu1XBase: nu1,
80}
81
82#[repr(C)]
83#[derive(Copy, Clone, Default, Debug)]
84pub struct Swap {
85    pub __Padding0: nu1,
86    pub __Padding1: nu1,
87    pub __Padding2: u2,
88    pub nu1XBase: nu1,
89    pub nu1YBase: nu1,
90    pub __Padding3: u2,
91    pub __Padding4: u2,
92    pub __Padding5: u2,
93    pub u2XLength: u2,
94}
95
96#[repr(C)]
97#[derive(Copy, Clone, Default, Debug)]
98pub struct ZpEcDsaGenerateFast {
99    pub nu1PointABase: nu1,
100    pub nu1OrderPointBase: nu1,
101    pub nu1ModBase: nu1,
102    pub nu1CnsBase: nu1,
103    pub nu1PrivateKey: nu1,
104    pub nu1ScalarNumber: nu1,
105    pub nu1ABase: nu1,
106    pub nu1HashBase: nu1,
107    pub nu1Workspace: nu1,
108    pub u2ModLength: u2,
109    pub u2ScalarLength: u2,
110    pub __Padding0: u2,
111}
112
113#[repr(C)]
114#[derive(Copy, Clone, Default, Debug)]
115pub struct ZpEcDsaVerifyFast {
116    pub nu1PointABase: nu1,
117    pub nu1OrderPointBase: nu1,
118    pub nu1ModBase: nu1,
119    pub nu1CnsBase: nu1,
120    pub nu1PointPublicKeyGen: nu1,
121    pub nu1PointSignature: nu1,
122    pub nu1ABase: nu1,
123    pub nu1HashBase: nu1,
124    pub nu1Workspace: nu1,
125    pub u2ModLength: u2,
126    pub u2ScalarLength: u2,
127    pub __Padding0: u2,
128}
129
130#[repr(C)]
131#[derive(Copy, Clone, Default, Debug)]
132pub struct ZpEcDsaQuickVerify {
133    pub pu1ModCnsBase: pu1,
134    pub pu1PointABase: pu1,
135    pub pu1PointPublicKeyGen: pu1,
136    pub pu1PointSignature: pu1,
137    pub pu1OrderPointBase: pu1,
138    pub pu1AWorkBase: pu1,
139    pub pu1HashBase: pu1,
140    pub u2ModLength: u2,
141    pub u2ScalarLength: u2,
142}
143
144#[repr(C)]
145#[derive(Copy, Clone, Default, Debug)]
146pub struct SelfTest {
147    pub u4Version: u4,
148    pub u4PUKCCVersion: u4,
149    pub u4CheckNum1: u4,
150    pub u4CheckNum2: u4,
151    pub u1Step: u1,
152}
153
154#[repr(C)]
155#[derive(Copy, Clone, Default, Debug)]
156pub struct ClearFlags {
157    pub __Padding0: nu1,
158    pub __Padding1: nu1,
159    pub __Padding2: u2,
160    pub __Padding3: u2,
161    pub __Padding4: u2,
162    pub __Padding5: u2,
163    pub __Padding6: u2,
164    pub __Padding7: u2,
165    pub __Padding8: u2,
166    pub __Padding9: u2,
167}
168
169#[repr(C)]
170#[derive(Copy, Clone, Default, Debug)]
171pub struct ZpEccMulFast {
172    pub nu1PointBase: nu1,
173    pub nu1ModBase: nu1,
174    pub nu1CnsBase: nu1,
175    pub nu1KBase: nu1,
176    pub nu1ABase: nu1,
177    pub nu1Workspace: nu1,
178    pub u2ModLength: u2,
179    pub u2KLength: u2,
180}
181
182#[repr(C)]
183#[derive(Copy, Clone, Default, Debug)]
184pub struct Square {
185    pub nu1ModBase: nu1,
186    pub nu1CnsBase: nu1,
187    pub u2ModLength: u2,
188    pub nu1XBase: nu1,
189    pub __Padding0: u2,
190    pub nu1ZBase: nu1,
191    pub nu1RBase: nu1,
192    pub __Padding1: u2,
193    pub u2XLength: u2,
194}
195
196#[repr(C)]
197#[derive(Copy, Clone, Default, Debug)]
198pub struct Fmult {
199    pub nu1ModBase: nu1,
200    pub nu1CnsBase: nu1,
201    pub u2ModLength: u2,
202    pub nu1XBase: nu1,
203    pub nu1YBase: nu1,
204    pub nu1ZBase: nu1,
205    pub nu1RBase: nu1,
206    pub u2XLength: u2,
207    pub u2YLength: u2,
208}
209
210#[repr(C)]
211#[derive(Copy, Clone, Default, Debug)]
212pub struct PrimeGen {
213    pub nu1RndBase: nu1,
214    pub nu1NBase: nu1,
215    pub nu1CnsBase: nu1,
216    pub nu1PrecompBase: nu1,
217    pub nu1RBase: nu1,
218    pub nu1ExpBase: nu1,
219    pub u2NLength: u2,
220    pub __Padding0: nu1,
221    pub u1MillerRabinIterations: u1,
222    pub __Padding1: u1,
223    pub u2MaxIncrement: u2,
224}
225
226#[repr(C)]
227#[derive(Copy, Clone, Default, Debug)]
228pub struct CondCopy {
229    pub __Padding0: nu1,
230    pub __Padding1: nu1,
231    pub __Padding2: u2,
232    pub nu1XBase: nu1,
233    pub __Padding3: u2,
234    pub __Padding4: u2,
235    pub nu1RBase: nu1,
236    pub u2RLength: u2,
237    pub u2XLength: u2,
238    pub __Padding5: u2,
239}
240
241#[repr(C)]
242#[derive(Copy, Clone, Default, Debug)]
243pub struct Div {
244    pub nu1ModBase: nu1,
245    pub nu1WorkSpace: nu1,
246    pub u2ModLength: u2,
247    pub nu1RBase: nu1,
248    pub __Padding0: u2,
249    pub nu1QuoBase: nu1,
250    pub nu1NumBase: nu1,
251    pub __Padding1: u2,
252    pub __Padding2: u2,
253    pub u2NumLength: u2,
254}
255
256#[repr(C)]
257#[derive(Copy, Clone, Default, Debug)]
258pub struct GF2NEccAddFast {
259    pub nu1PointABase: nu1,
260    pub nu1PointBBase: nu1,
261    pub nu1ModBase: nu1,
262    pub nu1CnsBase: nu1,
263    pub u2ModLength: u2,
264    pub nu1Workspace: nu1,
265    pub nu1ABBase: nu1,
266    pub __Padding1: nu1,
267}
268
269#[repr(C)]
270#[derive(Copy, Clone, Default, Debug)]
271pub struct Comp {
272    pub __Padding0: nu1,
273    pub __Padding1: nu1,
274    pub __Padding2: u2,
275    pub nu1XBase: nu1,
276    pub nu1YBase: nu1,
277    pub __Padding3: u2,
278    pub __Padding4: u2,
279    pub u2YLength: u2,
280    pub u2XLength: u2,
281}
282
283#[repr(C)]
284#[derive(Copy, Clone, Default, Debug)]
285pub struct ZpEccAddFast {
286    pub nu1PointABase: nu1,
287    pub nu1PointBBase: nu1,
288    pub nu1ModBase: nu1,
289    pub nu1CnsBase: nu1,
290    pub u2ModLength: u2,
291    pub nu1Workspace: nu1,
292    pub __Padding0: nu1,
293    pub __Padding1: nu1,
294}
295
296#[repr(C)]
297#[derive(Copy, Clone, Default, Debug)]
298pub struct GF2NEcDsaGenerateFast {
299    pub nu1PointABase: nu1,
300    pub nu1OrderPointBase: nu1,
301    pub nu1ModBase: nu1,
302    pub nu1CnsBase: nu1,
303    pub nu1PrivateKey: nu1,
304    pub nu1ScalarNumber: nu1,
305    pub nu1ABase: nu1,
306    pub nu1HashBase: nu1,
307    pub nu1Workspace: nu1,
308    pub u2ModLength: u2,
309    pub u2ScalarLength: u2,
310    pub __Padding0: u2,
311}
312
313#[repr(C)]
314#[derive(Copy, Clone, Default, Debug)]
315pub struct GF2NEcDsaVerifyFast {
316    pub nu1PointABase: nu1,
317    pub nu1OrderPointBase: nu1,
318    pub nu1ModBase: nu1,
319    pub nu1CnsBase: nu1,
320    pub nu1PointPublicKeyGen: nu1,
321    pub nu1PointSignature: nu1,
322    pub nu1ABase: nu1,
323    pub nu1HashBase: nu1,
324    pub nu1Workspace: nu1,
325    pub u2ModLength: u2,
326    pub u2ScalarLength: u2,
327    pub __Padding0: u2,
328}
329
330#[repr(C)]
331#[derive(Copy, Clone, Default, Debug)]
332pub struct CRT {
333    pub nu1XBase: nu1,
334    pub nu1ModBase: nu1,
335    pub nu1PrecompBase: nu1,
336    pub __Padding0: nu1,
337    pub pfu1ExpBase: pfu1,
338    pub u2ModLength: u2,
339    pub u2ExpLength: u2,
340    pub u1Blinding: u1,
341    pub __Padding1: u1,
342    pub __Padding2: u2,
343}
344
345#[repr(C)]
346#[derive(Copy, Clone, Default, Debug)]
347pub struct Rng {
348    pub nu1XKeyBase: nu1,
349    pub nu1WorkSpace: nu1,
350    pub u2XKeyLength: u2,
351    pub nu1XSeedBase: nu1,
352    pub nu1WorkSpace2: nu1,
353    pub nu1QBase: nu1,
354    pub nu1RBase: nu1,
355    pub u2RLength: u2,
356    pub u2X9_31Rounds: u2,
357    pub __Padding1: u2,
358}
359
360#[repr(C)]
361#[derive(Copy, Clone, Default, Debug)]
362pub struct GCD {
363    pub __Padding0: u2,
364    pub nu1WorkSpace: nu1,
365    pub __Padding1: u2,
366    pub nu1XBase: nu1,
367    pub nu1YBase: nu1,
368    pub nu1ABase: nu1,
369    pub nu1ZBase: nu1,
370    pub u2Length: u2,
371}
372
373bitfield! {
374    #[repr(C)]
375    #[derive(Copy, Clone, Default)]
376    pub struct PukclStatus(u32);
377    impl Debug;
378    u32;
379    carry_in, _: 0;
380    carry_out, _: 1;
381    zero, _: 2;
382    gf2n, _: 3;
383    violation, _: 4;
384}
385
386#[repr(C)]
387#[derive(Copy, Clone, Default, Debug)]
388pub struct PukclHeader {
389    pub u1Service: u1,
390    pub u1SubService: u1,
391    pub u2Option: u2,
392    pub Specific: PukclStatus,
393    pub u2Status: PukclReturnCode,
394    pub __Padding0: u2,
395    pub __Padding1: u4,
396}
397
398#[repr(C)]
399#[derive(Copy, Clone, Default)]
400pub struct PukclReturnCode(pub u2);
401
402impl core::fmt::Debug for PukclReturnCode {
403    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
404        super::PukclReturnCode::from(*self).fmt(f)
405    }
406}
407
408#[repr(C)]
409#[derive(Copy, Clone)]
410pub union PukclParamsUnion {
411    pub ClearFlags: ClearFlags,
412    pub Comp: Comp,
413    pub CondCopy: CondCopy,
414    pub CRT: CRT,
415    pub Div: Div,
416    pub ExpMod: ExpMod,
417    pub FastCopy: FastCopy,
418    pub Fill: Fill,
419    pub Fmult: Fmult,
420    pub GCD: GCD,
421    pub PrimeGen: PrimeGen,
422    pub RedMod: RedMod,
423    pub Rng: Rng,
424    pub SelfTest: SelfTest,
425    pub Smult: Smult,
426    pub Square: Square,
427    pub Swap: Swap,
428
429    /* ECC on Prime Field */
430    pub ZpEccAddFast: ZpEccAddFast,
431    pub ZpEccDblFast: ZpEccDblFast,
432    pub ZpEccAddSubFast: ZpEccAddSubFast,
433    pub ZpEccMulFast: ZpEccMulFast,
434    pub ZpEcDsaGenerateFast: ZpEcDsaGenerateFast,
435    pub ZpEcDsaVerifyFast: ZpEcDsaVerifyFast,
436    pub ZpEcDsaQuickVerify: ZpEcDsaQuickVerify,
437    pub ZpEccQuickDualMulFast: ZpEccQuickDualMulFast,
438    pub ZpEcConvProjToAffine: ZpEcConvProjToAffine,
439    pub ZpEcConvAffineToProjective: ZpEcConvAffineToProjective,
440    pub ZpEcRandomiseCoordinate: ZpEcRandomiseCoordinate,
441    pub ZpEcPointIsOnCurve: ZpEcPointIsOnCurve,
442
443    /* ECC on Binary Field */
444    pub GF2NEccAddFast: GF2NEccAddFast,
445    pub GF2NEccDblFast: GF2NEccDblFast,
446    pub GF2NEccMulFast: GF2NEccMulFast,
447    pub GF2NEcDsaGenerateFast: GF2NEcDsaGenerateFast,
448    pub GF2NEcDsaVerifyFast: GF2NEcDsaVerifyFast,
449    pub GF2NEcConvProjToAffine: GF2NEcConvProjToAffine,
450    pub GF2NEcConvAffineToProjective: GF2NEcConvAffineToProjective,
451    pub GF2NEcRandomiseCoordinate: GF2NEcRandomiseCoordinate,
452    pub GF2NEcPointIsOnCurve: GF2NEcPointIsOnCurve,
453}
454
455impl core::default::Default for PukclParamsUnion {
456    fn default() -> Self {
457        Self {
458            ClearFlags: Default::default(),
459        }
460    }
461}
462
463#[repr(C)]
464#[derive(Copy, Clone, Default)]
465pub struct PukclParams {
466    pub header: PukclHeader,
467    pub params: PukclParamsUnion,
468}
469
470impl core::fmt::Debug for PukclParams {
471    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
472        f.debug_struct("PukclParams")
473            .field("header", &self.header)
474            .field(
475                "params",
476                match debug_union_matcher(self) {
477                    Ok(field) => field,
478                    Err(_) => &"invalid service",
479                },
480            )
481            .finish()
482    }
483}
484
485#[repr(C)]
486#[derive(Copy, Clone, Default, Debug)]
487pub struct ZpEccQuickDualMulFast {
488    pub pu1ModCnsBase: pu1,
489    pub pu1PointABase: pu1,
490    pub pu1PointBBase: pu1,
491    pub pu1KABBase: pu1,
492    pub pu1AWorkBase: pu1,
493    pub u2ModLength: u2,
494    pub u2KLength: u2,
495}
496
497#[repr(C)]
498#[derive(Copy, Clone, Default, Debug)]
499pub struct GF2NEccDblFast {
500    pub nu1PointABase: nu1,
501    pub nu1ModBase: nu1,
502    pub nu1CnsBase: nu1,
503    pub nu1ABBase: nu1,
504    pub nu1Workspace: nu1,
505    pub u2ModLength: u2,
506    pub __Padding0: nu1,
507    pub __Padding1: nu1,
508}
509
510#[repr(C)]
511#[derive(Copy, Clone, Default, Debug)]
512pub struct ZpEccDblFast {
513    pub nu1PointABase: nu1,
514    pub nu1ModBase: nu1,
515    pub nu1CnsBase: nu1,
516    pub nu1ABase: nu1,
517    pub nu1Workspace: nu1,
518    pub u2ModLength: u2,
519    pub __Padding0: nu1,
520    pub __Padding1: nu1,
521}
522
523#[repr(C)]
524#[derive(Copy, Clone, Default, Debug)]
525pub struct ExpMod {
526    pub nu1XBase: nu1,
527    pub nu1ModBase: nu1,
528    pub nu1CnsBase: nu1,
529    pub nu1PrecompBase: nu1,
530    pub pfu1ExpBase: pfu1,
531    pub u2ModLength: u2,
532    pub u2ExpLength: u2,
533    pub u1Blinding: u1,
534    pub __Padding0: u1,
535    pub __Padding1: u2,
536}
537
538#[repr(C)]
539#[derive(Copy, Clone, Default, Debug)]
540pub struct GF2NEcConvProjToAffine {
541    pub nu1ModBase: nu1,
542    pub nu1CnsBase: nu1,
543    pub u2ModLength: u2,
544    pub nu1PointABase: nu1,
545    pub __Padding0: nu1,
546    pub nu1Workspace: nu1,
547}
548
549#[repr(C)]
550#[derive(Copy, Clone, Default, Debug)]
551pub struct GF2NEcConvAffineToProjective {
552    pub nu1ModBase: nu1,
553    pub nu1CnsBase: nu1,
554    pub u2ModLength: u2,
555    pub nu1PointABase: nu1,
556    pub __Padding0: nu1,
557    pub nu1Workspace: nu1,
558    pub __Padding1: nu1,
559    pub __Padding2: nu1,
560    pub __Padding3: nu1,
561    pub __Padding4: nu1,
562}
563
564#[repr(C)]
565#[derive(Copy, Clone, Default, Debug)]
566pub struct GF2NEcPointIsOnCurve {
567    pub nu1ModBase: nu1,
568    pub nu1CnsBase: nu1,
569    pub u2ModLength: u2,
570    pub nu1AParam: nu1,
571    pub nu1BParam: nu1,
572    pub nu1PointBase: nu1,
573    pub nu1Workspace: nu1,
574    pub __Padding0: u2,
575    pub __Padding1: u2,
576}
577
578#[repr(C)]
579#[derive(Copy, Clone, Default, Debug)]
580pub struct GF2NEcRandomiseCoordinate {
581    pub nu1ModBase: nu1,
582    pub nu1CnsBase: nu1,
583    pub u2ModLength: u2,
584    pub nu1PointBase: nu1,
585    pub nu1RandomBase: nu1,
586    pub nu1Workspace: nu1,
587    pub __Padding0: nu1,
588    pub __Padding1: nu1,
589    pub __Padding2: nu1,
590    pub __Padding3: nu1,
591}
592
593#[repr(C)]
594#[derive(Copy, Clone, Default, Debug)]
595pub struct FastCopy {
596    pub __Padding0: nu1,
597    pub __Padding1: nu1,
598    pub __Padding2: u2,
599
600    pub nu1XBase: nu1,
601    pub __Padding3: u2,
602    pub __Padding4: u2,
603    pub nu1RBase: nu1,
604    pub u2RLength: u2,
605    pub u2XLength: u2,
606    pub __Padding5: u2,
607}
608
609#[repr(C)]
610#[derive(Copy, Clone, Default, Debug)]
611pub struct ZpEcConvProjToAffine {
612    pub nu1ModBase: nu1,
613    pub nu1CnsBase: nu1,
614    pub u2ModLength: u2,
615    pub nu1PointABase: nu1,
616    pub __Padding0: nu1,
617    pub nu1Workspace: nu1,
618}
619
620#[repr(C)]
621#[derive(Copy, Clone, Default, Debug)]
622pub struct ZpEcConvAffineToProjective {
623    pub nu1ModBase: nu1,
624    pub nu1CnsBase: nu1,
625    pub u2ModLength: u2,
626    pub nu1PointABase: nu1,
627    pub __Padding0: nu1,
628    pub nu1Workspace: nu1,
629    pub __Padding1: nu1,
630    pub __Padding2: nu1,
631    pub __Padding3: nu1,
632    pub __Padding4: nu1,
633}
634
635#[repr(C)]
636#[derive(Copy, Clone, Default, Debug)]
637pub struct ZpEcPointIsOnCurve {
638    pub nu1ModBase: nu1,
639    pub nu1CnsBase: nu1,
640    pub u2ModLength: u2,
641    pub nu1AParam: nu1,
642    pub nu1BParam: nu1,
643    pub nu1PointBase: nu1,
644    pub nu1Workspace: nu1,
645    pub __Padding0: u2,
646    pub __Padding1: u2,
647}
648
649#[repr(C)]
650#[derive(Copy, Clone, Default, Debug)]
651pub struct ZpEcRandomiseCoordinate {
652    pub nu1ModBase: nu1,
653    pub nu1CnsBase: nu1,
654    pub u2ModLength: u2,
655    pub nu1PointBase: nu1,
656    pub nu1RandomBase: nu1,
657    pub nu1Workspace: nu1,
658    pub __Padding0: nu1,
659    pub __Padding1: nu1,
660    pub __Padding2: nu1,
661    pub __Padding3: nu1,
662}
663
664pub trait Service: crate::typelevel::Sealed {
665    const SERVICE_NUM: u8;
666    const FUNCTION_ADDRESS: usize;
667    /// Call to PUKCC functions
668    ///
669    /// # Safety
670    ///
671    /// User must ensure that [`PukclParams`] is correctly initialised
672    /// according to the service being called
673    unsafe fn call(pukcl_params: &mut PukclParams) {
674        pukcl_params.header.u1Service = Self::SERVICE_NUM;
675        pukcl_params.header.u2Status =
676            super::PukclReturnCode::Severe(super::PukclReturnCodeSevere::ComputationNotStarted)
677                .into();
678        core::mem::transmute::<usize, extern "C" fn(*mut PukclParams)>(Self::FUNCTION_ADDRESS)(
679            pukcl_params,
680        )
681    }
682}
683
684const JUMP_TABLE_START: usize = 0x02000001;
685
686/// Macro implementing a concept of jump table for all the services provided by
687/// PUKCC
688macro_rules! services {
689        (
690            $(
691                ($service_num:literal, $jump_table_offset:literal, $service:ident)
692            ),+
693        ) =>
694        {
695            // TODO: Maybe there's a better way of doing this?
696            /// A function that provides matching for a service identifier with an union variant
697            /// Used in a custom [`Debug`] trait implementation for a [`PukclParams`]
698            fn debug_union_matcher(pukcl_params: &PukclParams) -> Result<&dyn core::fmt::Debug, u8> {
699                match pukcl_params.header.u1Service {
700                    $(
701                        $service_num => Ok(unsafe { &pukcl_params.params.$service }),
702                    )+
703                    unknown_value => Err(unknown_value)
704                }
705            }
706            $(
707                impl Service for $service {
708                    const SERVICE_NUM: u8 = $service_num;
709                    const FUNCTION_ADDRESS: usize = JUMP_TABLE_START + $jump_table_offset;
710                }
711                impl crate::typelevel::Sealed for $service {}
712            )+
713        }
714    }
715
716services!(
717    (0x50, 0x08, RedMod),
718    (0x51, 0x0c, CondCopy),
719    (0x52, 0x50, Div),
720    (0x53, 0x28, ZpEcDsaGenerateFast),
721    (0x54, 0x04, GF2NEcRandomiseCoordinate),
722    (0x55, 0x2c, ZpEcDsaVerifyFast),
723    (0x56, 0x84, ZpEcConvProjToAffine),
724    (0x57, 0x6c, GF2NEcPointIsOnCurve),
725    (0x58, 0x5c, CRT),
726    (0x59, 0x30, GF2NEccAddFast),
727    (0x5b, 0x54, SelfTest),
728    (0x5c, 0x60, FastCopy),
729    (0x5d, 0x1c, GCD),
730    (0x5e, 0x78, ZpEcRandomiseCoordinate),
731    (0x5f, 0x10, ClearFlags),
732    (0x60, 0x34, ZpEccDblFast),
733    (0x61, 0x68, ZpEcConvAffineToProjective),
734    (0x62, 0x70, Rng),
735    (0x63, 0x74, Swap),
736    (0x64, 0x20, GF2NEccMulFast),
737    (0x65, 0x40, ZpEccMulFast),
738    (0x66, 0x38, ZpEccAddFast),
739    (0x67, 0x48, Smult),
740    (0x68, 0x8c, ZpEcPointIsOnCurve),
741    (0x69, 0x14, GF2NEccDblFast),
742    (0x6b, 0x24, Comp),
743    (0x6c, 0x80, ExpMod),
744    (0x6d, 0x4c, Square),
745    (0x6e, 0x58, PrimeGen),
746    (0x6f, 0x3c, Fill),
747    (0x70, 0x64, GF2NEcDsaGenerateFast),
748    (0x71, 0x18, Fmult),
749    (0x72, 0x88, GF2NEcConvProjToAffine),
750    (0x73, 0x7c, GF2NEcConvAffineToProjective),
751    (0x74, 0x44, GF2NEcDsaVerifyFast),
752    (0x75, 0x94, ZpEccAddSubFast),
753    (0x76, 0x98, ZpEccQuickDualMulFast),
754    (0x77, 0x9c, ZpEcDsaQuickVerify)
755);
756
757/// Function that has to be called before using PUKCC peripheral
758///
759/// # Safety
760///
761/// Defensively put as unsafe
762///
763/// Only useful for low-level ABI calls
764pub unsafe fn wait_for_crypto_ram_clear_process() {
765    const PUKCCSR: *mut u32 = 0x4200302C as _;
766    const BIT_PUKCCSR_CLRRAM_BUSY: u32 = 0x1;
767
768    while core::ptr::read_volatile(PUKCCSR) & BIT_PUKCCSR_CLRRAM_BUSY != 0 {}
769}
770
771/// Slice wrapper that provides Rust-like access to CryptoRAM memory area
772pub struct CryptoRam(&'static mut [u8]);
773
774impl CryptoRam {
775    const CRYPTORAM_BASE: *mut u8 = 0x02011000 as _;
776    const CRYPTORAM_LENGTH: usize = 0x1000;
777    /// Create CryptoRam
778    ///
779    /// # Safety
780    ///
781    /// Might break aliasing rules if more than one instance is used.
782    ///
783    /// Only to be used exclusively for low-level access,
784    /// never together with the high level API.
785    pub unsafe fn new() -> Self {
786        Self(core::slice::from_raw_parts_mut(
787            Self::CRYPTORAM_BASE,
788            Self::CRYPTORAM_LENGTH,
789        ))
790    }
791}
792
793/// Trait implemented for all `&[u8]` slices in order to provide a normalized
794/// way of downcasting pointers in a form accepted by PUKCC ABI
795pub trait CryptoRamSlice: crate::typelevel::Sealed {
796    /// Take a slice base-pointer and mask out a halfword according to
797    /// the expected format of CryptoRAM pointers in [`PukclParams`]-related
798    /// structs.
799    ///
800    /// # Safety
801    ///
802    /// Might break aliasing rules if more than one instance is used.
803    ///
804    /// Only to be used exclusively for low-level access,
805    /// never together with the high level API.
806    unsafe fn pukcc_base(&self) -> nu1;
807}
808
809impl CryptoRamSlice for &[u8] {
810    unsafe fn pukcc_base(&self) -> nu1 {
811        (self.as_ptr() as usize & 0x0000FFFF).try_into().unwrap()
812    }
813}
814
815impl crate::typelevel::Sealed for &[u8] {}
816
817impl core::ops::Deref for CryptoRam {
818    type Target = [u8];
819    fn deref(&self) -> &Self::Target {
820        self.0
821    }
822}
823
824impl core::ops::DerefMut for CryptoRam {
825    fn deref_mut(&mut self) -> &mut Self::Target {
826        self.0
827    }
828}