1use core::marker::PhantomData;
23
24use crate::{
25 Blocking,
26 DriverMode,
27 interrupt::InterruptHandler,
28 pac,
29 peripherals::{ECC, Interrupt},
30 reg_access::{AlignmentHelper, SocDependentEndianess},
31 system::{self, GenericPeripheralGuard},
32};
33
34pub struct Ecc<'d, Dm: DriverMode> {
36 ecc: ECC<'d>,
37 alignment_helper: AlignmentHelper<SocDependentEndianess>,
38 phantom: PhantomData<Dm>,
39 _guard: GenericPeripheralGuard<{ system::Peripheral::Ecc as u8 }>,
40}
41
42#[derive(Debug)]
44pub enum Error {
45 SizeMismatchCurve,
48 PointNotOnSelectedCurve,
50}
51
52pub enum EllipticCurve {
54 P192 = 0,
56 P256 = 1,
58}
59
60#[derive(Clone)]
61pub enum WorkMode {
64 PointMultiMode = 0,
66 #[cfg(esp32c2)]
67 DivisionMode = 1,
69 PointVerif = 2,
71 PointVerifMulti = 3,
73 JacobianPointMulti = 4,
75 #[cfg(esp32h2)]
76 PointAdd = 5,
78 JacobianPointVerif = 6,
80 PointVerifJacobianMulti = 7,
82 #[cfg(esp32h2)]
83 ModAdd = 8,
85 #[cfg(esp32h2)]
86 ModSub = 9,
88 #[cfg(esp32h2)]
89 ModMulti = 10,
91 #[cfg(esp32h2)]
92 ModDiv = 11,
94}
95
96impl<'d> Ecc<'d, Blocking> {
97 pub fn new(ecc: ECC<'d>) -> Self {
99 let guard = GenericPeripheralGuard::new();
100
101 Self {
102 ecc,
103 alignment_helper: AlignmentHelper::default(),
104 phantom: PhantomData,
105 _guard: guard,
106 }
107 }
108}
109
110impl crate::private::Sealed for Ecc<'_, Blocking> {}
111
112#[instability::unstable]
113impl crate::interrupt::InterruptConfigurable for Ecc<'_, Blocking> {
114 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
115 self.set_interrupt_handler(handler);
116 }
117}
118
119impl<Dm: DriverMode> Ecc<'_, Dm> {
120 fn regs(&self) -> &pac::ecc::RegisterBlock {
121 self.ecc.register_block()
122 }
123
124 pub fn reset(&mut self) {
126 self.regs().mult_conf().reset()
127 }
128
129 pub fn affine_point_multiplication(
141 &mut self,
142 curve: &EllipticCurve,
143 k: &[u8],
144 x: &mut [u8],
145 y: &mut [u8],
146 ) -> Result<(), Error> {
147 let curve = match curve {
148 EllipticCurve::P192 => {
149 if k.len() != 24 || x.len() != 24 || y.len() != 24 {
150 return Err(Error::SizeMismatchCurve);
151 }
152 false
153 }
154 EllipticCurve::P256 => {
155 if k.len() != 32 || x.len() != 32 || y.len() != 32 {
156 return Err(Error::SizeMismatchCurve);
157 }
158 true
159 }
160 };
161 let mode = WorkMode::PointMultiMode;
162
163 let mut tmp = [0_u8; 32];
164 self.reverse_words(k, &mut tmp);
165 self.alignment_helper.volatile_write_regset(
166 self.regs().k_mem(0).as_ptr(),
167 tmp.as_ref(),
168 32,
169 );
170 self.reverse_words(x, &mut tmp);
171 self.alignment_helper.volatile_write_regset(
172 self.regs().px_mem(0).as_ptr(),
173 tmp.as_ref(),
174 32,
175 );
176 self.reverse_words(y, &mut tmp);
177 self.alignment_helper.volatile_write_regset(
178 self.regs().py_mem(0).as_ptr(),
179 tmp.as_ref(),
180 32,
181 );
182
183 self.regs().mult_conf().write(|w| unsafe {
184 w.work_mode()
185 .bits(mode as u8)
186 .key_length()
187 .bit(curve)
188 .start()
189 .set_bit()
190 });
191
192 while self.is_busy() {}
194
195 self.alignment_helper
196 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 32);
197 self.reverse_words(tmp.as_ref(), x);
198 self.alignment_helper
199 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
200 self.reverse_words(tmp.as_ref(), y);
201
202 Ok(())
203 }
204
205 #[cfg(esp32c2)]
217 pub fn finite_field_division(
218 &mut self,
219 curve: &EllipticCurve,
220 k: &[u8],
221 y: &mut [u8],
222 ) -> Result<(), Error> {
223 let curve = match curve {
224 EllipticCurve::P192 => {
225 if k.len() != 24 || y.len() != 24 {
226 return Err(Error::SizeMismatchCurve);
227 }
228 false
229 }
230 EllipticCurve::P256 => {
231 if k.len() != 32 || y.len() != 32 {
232 return Err(Error::SizeMismatchCurve);
233 }
234 true
235 }
236 };
237 let mode = WorkMode::DivisionMode;
238
239 let mut tmp = [0_u8; 32];
240 self.reverse_words(k, &mut tmp);
241 self.alignment_helper.volatile_write_regset(
242 self.regs().k_mem(0).as_ptr(),
243 tmp.as_ref(),
244 32,
245 );
246 self.reverse_words(y, &mut tmp);
247 self.alignment_helper.volatile_write_regset(
248 self.regs().py_mem(0).as_ptr(),
249 tmp.as_ref(),
250 32,
251 );
252
253 self.regs().mult_conf().write(|w| unsafe {
254 w.work_mode()
255 .bits(mode as u8)
256 .key_length()
257 .bit(curve)
258 .start()
259 .set_bit()
260 });
261
262 while self.is_busy() {}
264
265 self.alignment_helper
266 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
267 self.reverse_words(tmp.as_ref(), y);
268
269 Ok(())
270 }
271
272 pub fn affine_point_verification(
285 &mut self,
286 curve: &EllipticCurve,
287 x: &[u8],
288 y: &[u8],
289 ) -> Result<(), Error> {
290 let curve = match curve {
291 EllipticCurve::P192 => {
292 if x.len() != 24 || y.len() != 24 {
293 return Err(Error::SizeMismatchCurve);
294 }
295 false
296 }
297 EllipticCurve::P256 => {
298 if x.len() != 32 || y.len() != 32 {
299 return Err(Error::SizeMismatchCurve);
300 }
301 true
302 }
303 };
304 let mode = WorkMode::PointVerif;
305
306 let mut tmp = [0_u8; 32];
307 self.reverse_words(x, &mut tmp);
308 self.alignment_helper.volatile_write_regset(
309 self.regs().px_mem(0).as_ptr(),
310 tmp.as_ref(),
311 32,
312 );
313 self.reverse_words(y, &mut tmp);
314 self.alignment_helper.volatile_write_regset(
315 self.regs().py_mem(0).as_ptr(),
316 tmp.as_ref(),
317 32,
318 );
319
320 self.regs().mult_conf().write(|w| unsafe {
321 w.work_mode()
322 .bits(mode as u8)
323 .key_length()
324 .bit(curve)
325 .start()
326 .set_bit()
327 });
328
329 while self.is_busy() {}
331
332 if !self.regs().mult_conf().read().verification_result().bit() {
333 self.regs().mult_conf().reset();
334 return Err(Error::PointNotOnSelectedCurve);
335 }
336
337 Ok(())
338 }
339
340 #[cfg(not(esp32h2))]
356 pub fn affine_point_verification_multiplication(
357 &mut self,
358 curve: &EllipticCurve,
359 k: &[u8],
360 x: &mut [u8],
361 y: &mut [u8],
362 ) -> Result<(), Error> {
363 let curve = match curve {
364 EllipticCurve::P192 => {
365 if k.len() != 24 || x.len() != 24 || y.len() != 24 {
366 return Err(Error::SizeMismatchCurve);
367 }
368 false
369 }
370 EllipticCurve::P256 => {
371 if k.len() != 32 || x.len() != 32 || y.len() != 32 {
372 return Err(Error::SizeMismatchCurve);
373 }
374 true
375 }
376 };
377 let mode = WorkMode::PointVerifMulti;
378
379 let mut tmp = [0_u8; 32];
380 self.reverse_words(k, &mut tmp);
381 self.alignment_helper.volatile_write_regset(
382 self.regs().k_mem(0).as_ptr(),
383 tmp.as_ref(),
384 32,
385 );
386 self.reverse_words(x, &mut tmp);
387 self.alignment_helper.volatile_write_regset(
388 self.regs().px_mem(0).as_ptr(),
389 tmp.as_ref(),
390 32,
391 );
392 self.reverse_words(y, &mut tmp);
393 self.alignment_helper.volatile_write_regset(
394 self.regs().py_mem(0).as_ptr(),
395 tmp.as_ref(),
396 32,
397 );
398
399 self.regs().mult_conf().write(|w| unsafe {
400 w.work_mode()
401 .bits(mode as u8)
402 .key_length()
403 .bit(curve)
404 .start()
405 .set_bit()
406 });
407
408 while self.is_busy() {}
410
411 if !self.regs().mult_conf().read().verification_result().bit() {
412 self.regs().mult_conf().reset();
413 return Err(Error::PointNotOnSelectedCurve);
414 }
415
416 self.alignment_helper
417 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 32);
418 self.reverse_words(tmp.as_ref(), x);
419 self.alignment_helper
420 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
421 self.reverse_words(tmp.as_ref(), y);
422
423 Ok(())
424 }
425
426 #[expect(clippy::too_many_arguments)]
444 #[cfg(esp32h2)]
445 pub fn affine_point_verification_multiplication(
446 &mut self,
447 curve: &EllipticCurve,
448 k: &[u8],
449 px: &mut [u8],
450 py: &mut [u8],
451 qx: &mut [u8],
452 qy: &mut [u8],
453 qz: &mut [u8],
454 ) -> Result<(), Error> {
455 let curve = match curve {
456 EllipticCurve::P192 => {
457 if k.len() != 24 || px.len() != 24 || py.len() != 24 {
458 return Err(Error::SizeMismatchCurve);
459 }
460 false
461 }
462 EllipticCurve::P256 => {
463 if k.len() != 32 || px.len() != 32 || py.len() != 32 {
464 return Err(Error::SizeMismatchCurve);
465 }
466 true
467 }
468 };
469 let mode = WorkMode::PointVerifMulti;
470
471 let mut tmp = [0_u8; 32];
472 self.reverse_words(k, &mut tmp);
473 self.alignment_helper.volatile_write_regset(
474 self.regs().k_mem(0).as_ptr(),
475 tmp.as_ref(),
476 32,
477 );
478 self.reverse_words(px, &mut tmp);
479 self.alignment_helper.volatile_write_regset(
480 self.regs().px_mem(0).as_ptr(),
481 tmp.as_ref(),
482 32,
483 );
484 self.reverse_words(py, &mut tmp);
485 self.alignment_helper.volatile_write_regset(
486 self.regs().py_mem(0).as_ptr(),
487 tmp.as_ref(),
488 32,
489 );
490
491 self.regs().mult_conf().write(|w| unsafe {
492 w.work_mode().bits(mode as u8);
493 w.key_length().bit(curve);
494 w.start().set_bit()
495 });
496
497 while self.is_busy() {}
499
500 if !self.regs().mult_conf().read().verification_result().bit() {
501 self.regs().mult_conf().reset();
502 return Err(Error::PointNotOnSelectedCurve);
503 }
504
505 self.alignment_helper
506 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 32);
507 self.reverse_words(tmp.as_ref(), px);
508 self.alignment_helper
509 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
510 self.reverse_words(tmp.as_ref(), py);
511 self.alignment_helper
512 .volatile_read_regset(self.regs().qx_mem(0).as_ptr(), &mut tmp, 32);
513 self.reverse_words(tmp.as_ref(), qx);
514 self.alignment_helper
515 .volatile_read_regset(self.regs().qy_mem(0).as_ptr(), &mut tmp, 32);
516 self.reverse_words(tmp.as_ref(), qy);
517 self.alignment_helper
518 .volatile_read_regset(self.regs().qz_mem(0).as_ptr(), &mut tmp, 32);
519 self.reverse_words(tmp.as_ref(), qz);
520
521 Ok(())
522 }
523
524 pub fn jacobian_point_multiplication(
536 &mut self,
537 curve: &EllipticCurve,
538 k: &mut [u8],
539 x: &mut [u8],
540 y: &mut [u8],
541 ) -> Result<(), Error> {
542 let curve = match curve {
543 EllipticCurve::P192 => {
544 if k.len() != 24 || x.len() != 24 || y.len() != 24 {
545 return Err(Error::SizeMismatchCurve);
546 }
547 false
548 }
549 EllipticCurve::P256 => {
550 if k.len() != 32 || x.len() != 32 || y.len() != 32 {
551 return Err(Error::SizeMismatchCurve);
552 }
553 true
554 }
555 };
556 let mode = WorkMode::JacobianPointMulti;
557
558 let mut tmp = [0_u8; 32];
559 self.reverse_words(k, &mut tmp);
560 self.alignment_helper.volatile_write_regset(
561 self.regs().k_mem(0).as_ptr(),
562 tmp.as_ref(),
563 32,
564 );
565 self.reverse_words(x, &mut tmp);
566 self.alignment_helper.volatile_write_regset(
567 self.regs().px_mem(0).as_ptr(),
568 tmp.as_ref(),
569 32,
570 );
571 self.reverse_words(y, &mut tmp);
572 self.alignment_helper.volatile_write_regset(
573 self.regs().py_mem(0).as_ptr(),
574 tmp.as_ref(),
575 32,
576 );
577
578 self.regs().mult_conf().write(|w| unsafe {
579 w.work_mode().bits(mode as u8);
580 w.key_length().bit(curve);
581 w.start().set_bit()
582 });
583
584 while self.is_busy() {}
585
586 cfg_if::cfg_if! {
587 if #[cfg(not(esp32h2))] {
588 self.alignment_helper
589 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 32);
590 self.reverse_words(tmp.as_ref(), x);
591 self.alignment_helper
592 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
593 self.reverse_words(tmp.as_ref(), y);
594 self.alignment_helper
595 .volatile_read_regset(self.regs().k_mem(0).as_ptr(), &mut tmp, 32);
596 self.reverse_words(tmp.as_ref(), k);
597 } else {
598 self.alignment_helper
599 .volatile_read_regset(self.regs().qx_mem(0).as_ptr(), &mut tmp, 32);
600 self.reverse_words(tmp.as_ref(), x);
601 self.alignment_helper
602 .volatile_read_regset(self.regs().qy_mem(0).as_ptr(), &mut tmp, 32);
603 self.reverse_words(tmp.as_ref(), y);
604 self.alignment_helper
605 .volatile_read_regset(self.regs().qz_mem(0).as_ptr(), &mut tmp, 32);
606 self.reverse_words(tmp.as_ref(), k);
607 }
608 }
609
610 Ok(())
611 }
612
613 pub fn jacobian_point_verification(
626 &mut self,
627 curve: &EllipticCurve,
628 x: &[u8],
629 y: &[u8],
630 z: &[u8],
631 ) -> Result<(), Error> {
632 let curve = match curve {
633 EllipticCurve::P192 => {
634 if x.len() != 24 || y.len() != 24 || z.len() != 24 {
635 return Err(Error::SizeMismatchCurve);
636 }
637 false
638 }
639 EllipticCurve::P256 => {
640 if x.len() != 32 || y.len() != 32 || z.len() != 32 {
641 return Err(Error::SizeMismatchCurve);
642 }
643 true
644 }
645 };
646 let mode = WorkMode::JacobianPointVerif;
647
648 let mut tmp = [0_u8; 32];
649 self.reverse_words(x, &mut tmp);
650
651 cfg_if::cfg_if! {
652 if #[cfg(not(esp32h2))] {
653 self.alignment_helper
654 .volatile_write_regset(self.regs().px_mem(0).as_ptr(), tmp.as_ref(), 32);
655 self.reverse_words(y, &mut tmp);
656 self.alignment_helper
657 .volatile_write_regset(self.regs().py_mem(0).as_ptr(), tmp.as_ref(), 32);
658 self.reverse_words(z, &mut tmp);
659 self.alignment_helper
660 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 32);
661 } else {
662 self.alignment_helper
663 .volatile_write_regset(self.regs().qx_mem(0).as_ptr(), tmp.as_ref(), 32);
664 self.reverse_words(y, &mut tmp);
665 self.alignment_helper
666 .volatile_write_regset(self.regs().qy_mem(0).as_ptr(), tmp.as_ref(), 32);
667 self.reverse_words(z, &mut tmp);
668 self.alignment_helper
669 .volatile_write_regset(self.regs().qz_mem(0).as_ptr(), tmp.as_ref(), 32);
670 }
671 }
672
673 self.regs().mult_conf().write(|w| unsafe {
674 w.work_mode()
675 .bits(mode as u8)
676 .key_length()
677 .bit(curve)
678 .start()
679 .set_bit()
680 });
681
682 while self.is_busy() {}
684
685 if !self.regs().mult_conf().read().verification_result().bit() {
686 self.regs().mult_conf().reset();
687 return Err(Error::PointNotOnSelectedCurve);
688 }
689
690 Ok(())
691 }
692
693 pub fn affine_point_verification_jacobian_multiplication(
709 &mut self,
710 curve: &EllipticCurve,
711 k: &mut [u8],
712 x: &mut [u8],
713 y: &mut [u8],
714 ) -> Result<(), Error> {
715 let curve = match curve {
716 EllipticCurve::P192 => {
717 if k.len() != 24 || x.len() != 24 || y.len() != 24 {
718 return Err(Error::SizeMismatchCurve);
719 }
720 false
721 }
722 EllipticCurve::P256 => {
723 if k.len() != 32 || x.len() != 32 || y.len() != 32 {
724 return Err(Error::SizeMismatchCurve);
725 }
726 true
727 }
728 };
729 let mode = WorkMode::PointVerifJacobianMulti;
730
731 let mut tmp = [0_u8; 32];
732 self.reverse_words(k, &mut tmp);
733 self.alignment_helper.volatile_write_regset(
734 self.regs().k_mem(0).as_ptr(),
735 tmp.as_ref(),
736 32,
737 );
738 self.reverse_words(x, &mut tmp);
739 self.alignment_helper.volatile_write_regset(
740 self.regs().px_mem(0).as_ptr(),
741 tmp.as_ref(),
742 32,
743 );
744 self.reverse_words(y, &mut tmp);
745 self.alignment_helper.volatile_write_regset(
746 self.regs().py_mem(0).as_ptr(),
747 tmp.as_ref(),
748 32,
749 );
750
751 self.regs().mult_conf().write(|w| unsafe {
752 w.work_mode().bits(mode as u8);
753 w.key_length().bit(curve);
754 w.start().set_bit()
755 });
756
757 while self.is_busy() {}
759
760 if !self.regs().mult_conf().read().verification_result().bit() {
761 self.regs().mult_conf().reset();
762 return Err(Error::PointNotOnSelectedCurve);
763 }
764
765 if !self.regs().mult_conf().read().verification_result().bit() {
766 self.regs().mult_conf().reset();
767 return Err(Error::PointNotOnSelectedCurve);
768 }
769
770 cfg_if::cfg_if! {
771 if #[cfg(not(esp32h2))] {
772 self.alignment_helper
773 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 32);
774 self.reverse_words(tmp.as_ref(), x);
775 self.alignment_helper
776 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
777 self.reverse_words(tmp.as_ref(), y);
778 self.alignment_helper
779 .volatile_read_regset(self.regs().k_mem(0).as_ptr(), &mut tmp, 32);
780 self.reverse_words(tmp.as_ref(), k);
781 } else {
782 self.alignment_helper
783 .volatile_read_regset(self.regs().qx_mem(0).as_ptr(), &mut tmp, 32);
784 self.reverse_words(tmp.as_ref(), x);
785 self.alignment_helper
786 .volatile_read_regset(self.regs().qy_mem(0).as_ptr(), &mut tmp, 32);
787 self.reverse_words(tmp.as_ref(), y);
788 self.alignment_helper
789 .volatile_read_regset(self.regs().qz_mem(0).as_ptr(), &mut tmp, 32);
790 self.reverse_words(tmp.as_ref(), k);
791 }
792 }
793
794 Ok(())
795 }
796
797 #[cfg(esp32h2)]
816 pub fn affine_point_addition(
817 &mut self,
818 curve: &EllipticCurve,
819 px: &mut [u8],
820 py: &mut [u8],
821 qx: &mut [u8],
822 qy: &mut [u8],
823 qz: &mut [u8],
824 ) -> Result<(), Error> {
825 let curve = match curve {
826 EllipticCurve::P192 => {
827 if px.len() != 24
828 || py.len() != 24
829 || qx.len() != 24
830 || qy.len() != 24
831 || qz.len() != 24
832 {
833 return Err(Error::SizeMismatchCurve);
834 }
835 false
836 }
837 EllipticCurve::P256 => {
838 if px.len() != 32
839 || py.len() != 32
840 || qx.len() != 32
841 || qy.len() != 32
842 || qz.len() != 32
843 {
844 return Err(Error::SizeMismatchCurve);
845 }
846 true
847 }
848 };
849 let mode = WorkMode::PointAdd;
850
851 let mut tmp = [0_u8; 32];
852
853 tmp[0..px.len()].copy_from_slice(px);
854 self.alignment_helper
855 .volatile_write_regset(self.regs().px_mem(0).as_ptr(), &tmp, 32);
856 tmp[0..py.len()].copy_from_slice(py);
857 self.alignment_helper
858 .volatile_write_regset(self.regs().py_mem(0).as_ptr(), &tmp, 32);
859 tmp[0..qx.len()].copy_from_slice(qx);
860 self.alignment_helper
861 .volatile_write_regset(self.regs().qx_mem(0).as_ptr(), &tmp, 32);
862 tmp[0..qy.len()].copy_from_slice(qy);
863 self.alignment_helper
864 .volatile_write_regset(self.regs().qy_mem(0).as_ptr(), &tmp, 32);
865 tmp[0..qz.len()].copy_from_slice(qz);
866 self.alignment_helper
867 .volatile_write_regset(self.regs().qz_mem(0).as_ptr(), &tmp, 32);
868
869 self.regs().mult_conf().write(|w| unsafe {
870 w.work_mode()
871 .bits(mode as u8)
872 .key_length()
873 .bit(curve)
874 .start()
875 .set_bit()
876 });
877
878 while self.is_busy() {}
880
881 self.alignment_helper
882 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 32);
883 let mut tmp_len = px.len();
884 px[..].copy_from_slice(&tmp[..tmp_len]);
885 self.alignment_helper
886 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 32);
887 tmp_len = py.len();
888 py[..].copy_from_slice(&tmp[..tmp_len]);
889 self.alignment_helper
890 .volatile_read_regset(self.regs().qx_mem(0).as_ptr(), &mut tmp, 32);
891 tmp_len = qx.len();
892 qx[..].copy_from_slice(&tmp[..tmp_len]);
893 self.alignment_helper
894 .volatile_read_regset(self.regs().qy_mem(0).as_ptr(), &mut tmp, 32);
895 tmp_len = qy.len();
896 qy[..].copy_from_slice(&tmp[..tmp_len]);
897 self.alignment_helper
898 .volatile_read_regset(self.regs().qz_mem(0).as_ptr(), &mut tmp, 32);
899 tmp_len = qz.len();
900 qz[..].copy_from_slice(&tmp[..tmp_len]);
901
902 Ok(())
903 }
904
905 #[cfg(esp32h2)]
922 pub fn mod_operations(
923 &mut self,
924 curve: &EllipticCurve,
925 a: &mut [u8],
926 b: &mut [u8],
927 work_mode: WorkMode,
928 ) -> Result<(), Error> {
929 let curve = match curve {
930 EllipticCurve::P192 => {
931 if a.len() != 24 || b.len() != 24 {
932 return Err(Error::SizeMismatchCurve);
933 }
934 false
935 }
936 EllipticCurve::P256 => {
937 if a.len() != 32 || b.len() != 32 {
938 return Err(Error::SizeMismatchCurve);
939 }
940 true
941 }
942 };
943
944 let mut tmp = [0_u8; 32];
945 tmp[0..a.len()].copy_from_slice(a);
946 self.alignment_helper
947 .volatile_write_regset(self.regs().px_mem(0).as_ptr(), &tmp, 32);
948 tmp[0..b.len()].copy_from_slice(b);
949 self.alignment_helper
950 .volatile_write_regset(self.regs().py_mem(0).as_ptr(), &tmp, 32);
951
952 self.regs().mult_conf().write(|w| unsafe {
953 w.work_mode()
954 .bits(work_mode.clone() as u8)
955 .key_length()
956 .bit(curve)
957 .start()
958 .set_bit()
959 });
960
961 while self.is_busy() {}
963
964 match work_mode {
965 WorkMode::ModAdd | WorkMode::ModSub => {
966 self.alignment_helper.volatile_read_regset(
967 self.regs().px_mem(0).as_ptr(),
968 &mut tmp,
969 32,
970 );
971 let tmp_len = a.len();
972 a[..].copy_from_slice(&tmp[..tmp_len]);
973 }
974 WorkMode::ModMulti | WorkMode::ModDiv => {
975 self.alignment_helper.volatile_read_regset(
976 self.regs().py_mem(0).as_ptr(),
977 &mut tmp,
978 32,
979 );
980 let tmp_len = b.len();
981 b[..].copy_from_slice(&tmp[..tmp_len]);
982 }
983 _ => unreachable!(),
984 }
985
986 Ok(())
987 }
988
989 #[instability::unstable]
994 pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
995 for core in crate::system::Cpu::other() {
996 crate::interrupt::disable(core, Interrupt::ECC);
997 }
998 unsafe { crate::interrupt::bind_interrupt(Interrupt::ECC, handler.handler()) };
999 unwrap!(crate::interrupt::enable(Interrupt::ECC, handler.priority()));
1000 }
1001
1002 fn is_busy(&self) -> bool {
1003 self.regs().mult_conf().read().start().bit_is_set()
1004 }
1005
1006 fn reverse_words(&self, src: &[u8], dst: &mut [u8]) {
1007 let n = core::cmp::min(src.len(), dst.len());
1008 let nsrc = if src.len() > n {
1009 src.split_at(n).0
1010 } else {
1011 src
1012 };
1013 let ndst = if dst.len() > n {
1014 dst.split_at_mut(n).0
1015 } else {
1016 dst
1017 };
1018 for (a, b) in nsrc.chunks_exact(4).zip(ndst.rchunks_exact_mut(4)) {
1019 b.copy_from_slice(&u32::from_be_bytes(a.try_into().unwrap()).to_ne_bytes());
1020 }
1021 }
1022}