1use core::marker::PhantomData;
29
30use crate::{
31 interrupt::InterruptHandler,
32 pac,
33 peripheral::{Peripheral, PeripheralRef},
34 peripherals::{Interrupt, ECC},
35 reg_access::{AlignmentHelper, SocDependentEndianess},
36 system::{self, GenericPeripheralGuard},
37 Blocking,
38 DriverMode,
39};
40
41pub struct Ecc<'d, Dm: DriverMode> {
43 ecc: PeripheralRef<'d, ECC>,
44 alignment_helper: AlignmentHelper<SocDependentEndianess>,
45 phantom: PhantomData<Dm>,
46 _guard: GenericPeripheralGuard<{ system::Peripheral::Ecc as u8 }>,
47}
48
49#[derive(Debug)]
51pub enum Error {
52 SizeMismatchCurve,
55 PointNotOnSelectedCurve,
57}
58
59pub enum EllipticCurve {
61 P192 = 0,
63 P256 = 1,
65}
66
67#[derive(Clone)]
68pub enum WorkMode {
71 PointMultiMode = 0,
73 #[cfg(esp32c2)]
74 DivisionMode = 1,
76 PointVerif = 2,
78 PointVerifMulti = 3,
80 JacobianPointMulti = 4,
82 #[cfg(esp32h2)]
83 PointAdd = 5,
85 JacobianPointVerif = 6,
87 PointVerifJacobianMulti = 7,
89 #[cfg(esp32h2)]
90 ModAdd = 8,
92 #[cfg(esp32h2)]
93 ModSub = 9,
95 #[cfg(esp32h2)]
96 ModMulti = 10,
98 #[cfg(esp32h2)]
99 ModDiv = 11,
101}
102
103impl<'d> Ecc<'d, Blocking> {
104 pub fn new(ecc: impl Peripheral<P = ECC> + 'd) -> Self {
106 crate::into_ref!(ecc);
107
108 let guard = GenericPeripheralGuard::new();
109
110 Self {
111 ecc,
112 alignment_helper: AlignmentHelper::default(),
113 phantom: PhantomData,
114 _guard: guard,
115 }
116 }
117}
118
119impl crate::private::Sealed for Ecc<'_, Blocking> {}
120
121#[instability::unstable]
122impl crate::interrupt::InterruptConfigurable for Ecc<'_, Blocking> {
123 fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
124 self.set_interrupt_handler(handler);
125 }
126}
127
128impl<Dm: DriverMode> Ecc<'_, Dm> {
129 fn regs(&self) -> &pac::ecc::RegisterBlock {
130 self.ecc.register_block()
131 }
132
133 pub fn reset(&mut self) {
135 self.regs().mult_conf().reset()
136 }
137
138 pub fn affine_point_multiplication(
150 &mut self,
151 curve: &EllipticCurve,
152 k: &[u8],
153 x: &mut [u8],
154 y: &mut [u8],
155 ) -> Result<(), Error> {
156 let curve = match curve {
157 EllipticCurve::P192 => {
158 if k.len() != 24 || x.len() != 24 || y.len() != 24 {
159 return Err(Error::SizeMismatchCurve);
160 }
161 false
162 }
163 EllipticCurve::P256 => {
164 if k.len() != 32 || x.len() != 32 || y.len() != 32 {
165 return Err(Error::SizeMismatchCurve);
166 }
167 true
168 }
169 };
170 let mode = WorkMode::PointMultiMode;
171
172 let mut tmp = [0_u8; 32];
173 self.reverse_words(k, &mut tmp);
174 self.alignment_helper
175 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 8);
176 self.reverse_words(x, &mut tmp);
177 self.alignment_helper.volatile_write_regset(
178 self.regs().px_mem(0).as_ptr(),
179 tmp.as_ref(),
180 8,
181 );
182 self.reverse_words(y, &mut tmp);
183 self.alignment_helper.volatile_write_regset(
184 self.regs().py_mem(0).as_ptr(),
185 tmp.as_ref(),
186 8,
187 );
188
189 self.regs().mult_conf().write(|w| unsafe {
190 w.work_mode()
191 .bits(mode as u8)
192 .key_length()
193 .bit(curve)
194 .start()
195 .set_bit()
196 });
197
198 while self.is_busy() {}
200
201 self.alignment_helper
202 .volatile_read_regset(self.regs().px_mem(0).as_ptr(), &mut tmp, 8);
203 self.reverse_words(tmp.as_ref(), x);
204 self.alignment_helper
205 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 8);
206 self.reverse_words(tmp.as_ref(), y);
207
208 Ok(())
209 }
210
211 #[cfg(esp32c2)]
223 pub fn finite_field_division(
224 &mut self,
225 curve: &EllipticCurve,
226 k: &[u8],
227 y: &mut [u8],
228 ) -> Result<(), Error> {
229 let curve = match curve {
230 EllipticCurve::P192 => {
231 if k.len() != 24 || y.len() != 24 {
232 return Err(Error::SizeMismatchCurve);
233 }
234 false
235 }
236 EllipticCurve::P256 => {
237 if k.len() != 32 || y.len() != 32 {
238 return Err(Error::SizeMismatchCurve);
239 }
240 true
241 }
242 };
243 let mode = WorkMode::DivisionMode;
244
245 let mut tmp = [0_u8; 32];
246 self.reverse_words(k, &mut tmp);
247 self.alignment_helper
248 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 8);
249 self.reverse_words(y, &mut tmp);
250 self.alignment_helper.volatile_write_regset(
251 self.regs().py_mem(0).as_ptr(),
252 tmp.as_ref(),
253 8,
254 );
255
256 self.regs().mult_conf().write(|w| unsafe {
257 w.work_mode()
258 .bits(mode as u8)
259 .key_length()
260 .bit(curve)
261 .start()
262 .set_bit()
263 });
264
265 while self.is_busy() {}
267
268 self.alignment_helper
269 .volatile_read_regset(self.regs().py_mem(0).as_ptr(), &mut tmp, 8);
270 self.reverse_words(tmp.as_ref(), y);
271
272 Ok(())
273 }
274
275 pub fn affine_point_verification(
288 &mut self,
289 curve: &EllipticCurve,
290 x: &[u8],
291 y: &[u8],
292 ) -> Result<(), Error> {
293 let curve = match curve {
294 EllipticCurve::P192 => {
295 if x.len() != 24 || y.len() != 24 {
296 return Err(Error::SizeMismatchCurve);
297 }
298 false
299 }
300 EllipticCurve::P256 => {
301 if x.len() != 32 || y.len() != 32 {
302 return Err(Error::SizeMismatchCurve);
303 }
304 true
305 }
306 };
307 let mode = WorkMode::PointVerif;
308
309 let mut tmp = [0_u8; 32];
310 self.reverse_words(x, &mut tmp);
311 self.alignment_helper.volatile_write_regset(
312 self.regs().px_mem(0).as_ptr(),
313 tmp.as_ref(),
314 8,
315 );
316 self.reverse_words(y, &mut tmp);
317 self.alignment_helper.volatile_write_regset(
318 self.regs().py_mem(0).as_ptr(),
319 tmp.as_ref(),
320 8,
321 );
322
323 self.regs().mult_conf().write(|w| unsafe {
324 w.work_mode()
325 .bits(mode as u8)
326 .key_length()
327 .bit(curve)
328 .start()
329 .set_bit()
330 });
331
332 while self.is_busy() {}
334
335 if !self.regs().mult_conf().read().verification_result().bit() {
336 self.regs().mult_conf().reset();
337 return Err(Error::PointNotOnSelectedCurve);
338 }
339
340 Ok(())
341 }
342
343 #[cfg(not(esp32h2))]
359 pub fn affine_point_verification_multiplication(
360 &mut self,
361 curve: &EllipticCurve,
362 k: &[u8],
363 x: &mut [u8],
364 y: &mut [u8],
365 ) -> Result<(), Error> {
366 let curve = match curve {
367 EllipticCurve::P192 => {
368 if k.len() != 24 || x.len() != 24 || y.len() != 24 {
369 return Err(Error::SizeMismatchCurve);
370 }
371 false
372 }
373 EllipticCurve::P256 => {
374 if k.len() != 32 || x.len() != 32 || y.len() != 32 {
375 return Err(Error::SizeMismatchCurve);
376 }
377 true
378 }
379 };
380 let mode = WorkMode::PointVerifMulti;
381
382 let mut tmp = [0_u8; 32];
383 self.reverse_words(k, &mut tmp);
384 self.alignment_helper
385 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 8);
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 8,
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 8,
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, 8);
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, 8);
421 self.reverse_words(tmp.as_ref(), y);
422
423 Ok(())
424 }
425
426 #[allow(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
474 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 8);
475 self.reverse_words(px, &mut tmp);
476 self.alignment_helper.volatile_write_regset(
477 self.regs().px_mem(0).as_ptr(),
478 tmp.as_ref(),
479 8,
480 );
481 self.reverse_words(py, &mut tmp);
482 self.alignment_helper.volatile_write_regset(
483 self.regs().py_mem(0).as_ptr(),
484 tmp.as_ref(),
485 8,
486 );
487
488 self.regs().mult_conf().write(|w| unsafe {
489 w.work_mode()
490 .bits(mode as u8)
491 .key_length()
492 .bit(curve)
493 .start()
494 .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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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
561 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 8);
562 self.reverse_words(x, &mut tmp);
563 self.alignment_helper.volatile_write_regset(
564 self.regs().px_mem(0).as_ptr(),
565 tmp.as_ref(),
566 8,
567 );
568 self.reverse_words(y, &mut tmp);
569 self.alignment_helper.volatile_write_regset(
570 self.regs().py_mem(0).as_ptr(),
571 tmp.as_ref(),
572 8,
573 );
574
575 self.regs().mult_conf().write(|w| unsafe {
576 w.work_mode()
577 .bits(mode as u8)
578 .key_length()
579 .bit(curve)
580 .start()
581 .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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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(), 8);
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(), 8);
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(), 8);
661 } else {
662 self.alignment_helper
663 .volatile_write_regset(self.regs().qx_mem(0).as_ptr(), tmp.as_ref(), 8);
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(), 8);
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(), 8);
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
734 .volatile_write_regset(self.regs().k_mem(0).as_ptr(), tmp.as_ref(), 8);
735 self.reverse_words(x, &mut tmp);
736 self.alignment_helper.volatile_write_regset(
737 self.regs().px_mem(0).as_ptr(),
738 tmp.as_ref(),
739 8,
740 );
741 self.reverse_words(y, &mut tmp);
742 self.alignment_helper.volatile_write_regset(
743 self.regs().py_mem(0).as_ptr(),
744 tmp.as_ref(),
745 8,
746 );
747
748 self.regs().mult_conf().write(|w| unsafe {
749 w.work_mode()
750 .bits(mode as u8)
751 .key_length()
752 .bit(curve)
753 .start()
754 .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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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, 8);
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 8,
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 8,
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}