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