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