1use keccak_rhdl::{IterativeInput, IterativeKeccak, KeccakState};
33use rhdl::prelude::*;
34use rhdl_fpga::core::dff::DFF;
35use rhdl_primitives::NoResetDff;
36
37use crate::digits::{CHAIN_COUNT, MessageBytes, MessageDigitArray, message_digits_kernel};
38
39pub const LEGACY_HASH_BYTES: usize = 32;
41
42pub const LEGACY_MASK_COUNT: usize = 16;
44
45pub const LEGACY_CHAIN_STEPS: usize = 15;
47
48pub const LEGACY_FUSED_PERMUTATIONS: usize = 1_173;
50
51pub const LEGACY_FUSED_PRIVATE_KEY_PERMUTATIONS: usize = 1_172;
53
54pub const LEGACY_ENDPOINT_BLOCKS: usize = 16;
56
57pub const LEGACY_FUSED_OUTPUT_BEATS: usize = 35;
59
60pub type LegacyHashLanes = [b64; 4];
62
63pub type LegacySegmentStore = [LegacyHashLanes; CHAIN_COUNT];
65
66pub type LegacyMaskStore = [LegacyHashLanes; LEGACY_MASK_COUNT];
68
69pub type LegacyPrivateSeedBytes = [b8; LEGACY_HASH_BYTES];
71
72pub type LegacyBeatBytes = [b8; 64];
74
75const PHASE_PRIVATE_SEED: u128 = 0;
76const PHASE_PUBLIC_SEED: u128 = 1;
77const PHASE_MASK: u128 = 2;
78const PHASE_SEGMENT_PRF: u128 = 3;
79const PHASE_SECRET_HASH: u128 = 4;
80const PHASE_CHAIN: u128 = 5;
81const PHASE_PUBLIC_KEY: u128 = 6;
82
83const FINAL_OUTPUT_BEAT: u128 = 34;
84const FULL_KEEP: u128 = u64::MAX as u128;
85const FINAL_KEEP: u128 = 0xffff_ffff;
86
87const _: () = {
88 assert!(CHAIN_COUNT == 67);
89 assert!(LEGACY_HASH_BYTES == 32);
90 assert!(LEGACY_MASK_COUNT == 16);
91 assert!(LEGACY_CHAIN_STEPS == 15);
92 assert!(LEGACY_FUSED_PERMUTATIONS == 1_173);
93 assert!(LEGACY_FUSED_PRIVATE_KEY_PERMUTATIONS == 1_172);
94 assert!(LEGACY_ENDPOINT_BLOCKS == 16);
95 assert!(LEGACY_FUSED_OUTPUT_BEATS == 35);
96};
97
98#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
100pub struct LegacyFusedInput {
101 pub start_valid: bool,
103 pub private_seed: LegacyPrivateSeedBytes,
105 pub message: MessageBytes,
107 pub output_credit_available: bool,
109 pub output_ready: bool,
111}
112
113#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
120pub struct LegacyFusedPrivateKeyInput {
121 pub start_valid: bool,
123 pub private_key: LegacyPrivateSeedBytes,
125 pub message: MessageBytes,
127 pub output_credit_available: bool,
129 pub output_ready: bool,
131}
132
133#[derive(Clone, Copy, Debug, Digital, Eq, PartialEq)]
135pub struct LegacyFusedBeat {
136 pub data: LegacyBeatBytes,
138 pub keep: b64,
140 pub last: bool,
142}
143
144impl Default for LegacyFusedBeat {
145 fn default() -> Self {
146 Self {
147 data: [b8(0); 64],
148 keep: b64(0),
149 last: false,
150 }
151 }
152}
153
154#[allow(clippy::struct_excessive_bools)] #[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
157pub struct LegacyFusedOutput {
158 pub start_ready: bool,
160 pub active: bool,
162 pub output_credit_reserved: bool,
164 pub output_valid: bool,
166 pub output: LegacyFusedBeat,
168 pub computed_done: bool,
170 pub output_credit_release: bool,
172 pub permutation_count: b11,
174 pub audit_error: bool,
176}
177
178#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
180pub struct LegacyPrfStateInput {
181 pub seed: LegacyHashLanes,
183 pub index: b16,
185}
186
187#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
189pub struct LegacySecretStateInput {
190 pub function_key: LegacyHashLanes,
192 pub secret_prf: LegacyHashLanes,
194}
195
196#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
198pub struct LegacyChainStateInput {
199 pub state: LegacyHashLanes,
201 pub mask: LegacyHashLanes,
203}
204
205#[derive(Clone, Copy, Debug, Digital, Eq, PartialEq)]
207pub struct LegacyEndpointBlockInput {
208 pub sponge: KeccakState,
210 pub endpoints: LegacySegmentStore,
212 pub block_index: b5,
214}
215
216impl Default for LegacyEndpointBlockInput {
217 fn default() -> Self {
218 Self {
219 sponge: [b64(0); 25],
220 endpoints: [[b64(0); 4]; CHAIN_COUNT],
221 block_index: b5(0),
222 }
223 }
224}
225
226#[derive(Clone, Copy, Debug, Digital, Eq, PartialEq)]
228pub struct LegacyOutputBeatInput {
229 pub signature: LegacySegmentStore,
231 pub public_seed: LegacyHashLanes,
233 pub public_key_hash: LegacyHashLanes,
235 pub beat_index: b6,
237}
238
239impl Default for LegacyOutputBeatInput {
240 fn default() -> Self {
241 Self {
242 signature: [[b64(0); 4]; CHAIN_COUNT],
243 public_seed: [b64(0); 4],
244 public_key_hash: [b64(0); 4],
245 beat_index: b6(0),
246 }
247 }
248}
249
250#[kernel]
252pub fn legacy_bytes_to_lanes_kernel(bytes: LegacyPrivateSeedBytes) -> LegacyHashLanes {
253 let mut lanes = [b64(0); 4];
254 for lane in 0..4 {
255 let byte_zero: b64 = bytes[lane * 8].resize();
256 let byte_one: b64 = bytes[lane * 8 + 1].resize();
257 let byte_two: b64 = bytes[lane * 8 + 2].resize();
258 let byte_three: b64 = bytes[lane * 8 + 3].resize();
259 let byte_four: b64 = bytes[lane * 8 + 4].resize();
260 let byte_five: b64 = bytes[lane * 8 + 5].resize();
261 let byte_six: b64 = bytes[lane * 8 + 6].resize();
262 let byte_seven: b64 = bytes[lane * 8 + 7].resize();
263 lanes[lane] = byte_zero
264 | (byte_one << 8)
265 | (byte_two << 16)
266 | (byte_three << 24)
267 | (byte_four << 32)
268 | (byte_five << 40)
269 | (byte_six << 48)
270 | (byte_seven << 56);
271 }
272 lanes
273}
274
275#[kernel]
277pub fn legacy_hash32_state_kernel(value: LegacyHashLanes) -> KeccakState {
278 let mut state = [b64(0); 25];
279 state[0] = value[0];
280 state[1] = value[1];
281 state[2] = value[2];
282 state[3] = value[3];
283 state[4] = b64(0x01);
284 state[16] = b64(0x8000_0000_0000_0000);
285 state
286}
287
288#[kernel]
290pub fn legacy_prf_state_kernel(input: LegacyPrfStateInput) -> KeccakState {
291 let mut state = [b64(0); 25];
292 let index_high_byte: b8 = (input.index >> 8).resize();
293 let index_low_byte: b8 = input.index.resize();
294 let index_high: b64 = index_high_byte.resize();
295 let index_low: b64 = index_low_byte.resize();
296 state[0] = b64(0x03) | (input.seed[0] << 8);
297 state[1] = (input.seed[0] >> 56) | (input.seed[1] << 8);
298 state[2] = (input.seed[1] >> 56) | (input.seed[2] << 8);
299 state[3] = (input.seed[2] >> 56) | (input.seed[3] << 8);
300 state[4] = (input.seed[3] >> 56) | (index_high << 8) | (index_low << 16) | b64(0x01_00_00_00);
301 state[16] = b64(0x8000_0000_0000_0000);
302 state
303}
304
305#[kernel]
307pub fn legacy_secret_state_kernel(input: LegacySecretStateInput) -> KeccakState {
308 let mut state = [b64(0); 25];
309 state[0] = input.function_key[0];
310 state[1] = input.function_key[1];
311 state[2] = input.function_key[2];
312 state[3] = input.function_key[3];
313 state[4] = input.secret_prf[0];
314 state[5] = input.secret_prf[1];
315 state[6] = input.secret_prf[2];
316 state[7] = input.secret_prf[3];
317 state[8] = b64(0x01);
318 state[16] = b64(0x8000_0000_0000_0000);
319 state
320}
321
322#[kernel]
324pub fn legacy_chain_state_kernel(input: LegacyChainStateInput) -> KeccakState {
325 legacy_hash32_state_kernel([
326 input.state[0] ^ input.mask[0],
327 input.state[1] ^ input.mask[1],
328 input.state[2] ^ input.mask[2],
329 input.state[3] ^ input.mask[3],
330 ])
331}
332
333#[kernel]
335pub fn legacy_digest_lanes_kernel(state: KeccakState) -> LegacyHashLanes {
336 [state[0], state[1], state[2], state[3]]
337}
338
339#[kernel]
346#[allow(clippy::needless_range_loop)] pub fn legacy_endpoint_block_state_kernel(input: LegacyEndpointBlockInput) -> KeccakState {
348 let mut state = input.sponge;
349 let block_wide: b9 = input.block_index.resize();
350 let base: b9 = (block_wide << 4) + block_wide;
351
352 if input.block_index < b5(15) {
353 for lane in 0..17 {
354 let absolute = base + b9(lane as u128);
355 let segment: b7 = (absolute >> 2).resize();
356 let word: b2 = absolute.resize();
357 state[lane] ^= input.endpoints[segment][word];
358 }
359 } else {
360 for lane in 0..13 {
361 let absolute = b9(255 + lane as u128);
362 let segment: b7 = (absolute >> 2).resize();
363 let word: b2 = absolute.resize();
364 state[lane] ^= input.endpoints[segment][word];
365 }
366 state[13] ^= b64(0x01);
367 state[16] ^= b64(0x8000_0000_0000_0000);
368 }
369 state
370}
371
372#[kernel]
374#[allow(clippy::comparison_chain, clippy::needless_range_loop)] pub fn legacy_output_beat_kernel(input: LegacyOutputBeatInput) -> LegacyFusedBeat {
376 let mut lanes = [b64(0); 8];
377 let mut keep = b64(FULL_KEEP);
378 let mut last = false;
379
380 if input.beat_index < b6(33) {
381 let beat_wide: b9 = input.beat_index.resize();
382 let base = beat_wide << 3;
383 for lane in 0..8 {
384 let absolute = base + b9(lane as u128);
385 let segment: b7 = (absolute >> 2).resize();
386 let word: b2 = absolute.resize();
387 lanes[lane] = input.signature[segment][word];
388 }
389 } else if input.beat_index == b6(33) {
390 lanes[0] = input.signature[66][0];
391 lanes[1] = input.signature[66][1];
392 lanes[2] = input.signature[66][2];
393 lanes[3] = input.signature[66][3];
394 lanes[4] = input.public_seed[0];
395 lanes[5] = input.public_seed[1];
396 lanes[6] = input.public_seed[2];
397 lanes[7] = input.public_seed[3];
398 } else {
399 lanes[0] = input.public_key_hash[0];
400 lanes[1] = input.public_key_hash[1];
401 lanes[2] = input.public_key_hash[2];
402 lanes[3] = input.public_key_hash[3];
403 keep = b64(FINAL_KEEP);
404 last = true;
405 }
406
407 let mut data = [b8(0); 64];
408 for lane in 0..8 {
409 data[lane * 8] = lanes[lane].resize();
410 data[lane * 8 + 1] = (lanes[lane] >> 8).resize();
411 data[lane * 8 + 2] = (lanes[lane] >> 16).resize();
412 data[lane * 8 + 3] = (lanes[lane] >> 24).resize();
413 data[lane * 8 + 4] = (lanes[lane] >> 32).resize();
414 data[lane * 8 + 5] = (lanes[lane] >> 40).resize();
415 data[lane * 8 + 6] = (lanes[lane] >> 48).resize();
416 data[lane * 8 + 7] = (lanes[lane] >> 56).resize();
417 }
418 LegacyFusedBeat { data, keep, last }
419}
420
421#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
422#[doc(hidden)]
423#[allow(clippy::struct_excessive_bools)] pub struct LegacyControl {
425 active: bool,
426 waiting: bool,
427 credit_reserved: bool,
428 result_valid: bool,
429 computed_done: bool,
430 credit_release: bool,
431 audit_error: bool,
432 from_private_seed: bool,
433 phase: b3,
434 mask_index: b5,
435 segment: b7,
436 chain_step: b4,
437 public_key_block: b5,
438 output_beat: b6,
439 permutation_count: b11,
440}
441
442#[derive(Clone, Copy, Debug, Default, Digital, Eq, PartialEq)]
443#[doc(hidden)]
444#[allow(clippy::struct_excessive_bools)] pub struct LegacyCoreInput {
446 start_valid: bool,
447 secret: LegacyPrivateSeedBytes,
448 message: MessageBytes,
449 output_credit_available: bool,
450 output_ready: bool,
451 from_private_seed: bool,
452}
453
454#[derive(Clone, Copy, Debug, Digital, Eq, PartialEq)]
455#[doc(hidden)]
456pub struct LegacyData {
457 private_seed: LegacyHashLanes,
458 message_digits: MessageDigitArray,
459 private_key: LegacyHashLanes,
460 public_seed: LegacyHashLanes,
461 masks: LegacyMaskStore,
462 signature: LegacySegmentStore,
463 endpoints: LegacySegmentStore,
464 secret_prf: LegacyHashLanes,
465 chain_state: LegacyHashLanes,
466 public_key_sponge: KeccakState,
467 public_key_hash: LegacyHashLanes,
468}
469
470#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
479#[rhdl(dq_no_prefix)]
480#[doc(hidden)]
481pub struct LegacyFusedCore {
482 keccak: IterativeKeccak,
483 control: DFF<LegacyControl>,
484 data: NoResetDff<LegacyData>,
485}
486
487impl Default for LegacyFusedCore {
488 fn default() -> Self {
489 Self {
490 keccak: IterativeKeccak::default(),
491 control: DFF::new(LegacyControl::default()),
492 data: NoResetDff::new(),
493 }
494 }
495}
496
497impl SynchronousIO for LegacyFusedCore {
498 type I = LegacyCoreInput;
499 type O = LegacyFusedOutput;
500 type Kernel = legacy_fused_core_kernel;
501}
502
503#[kernel]
504#[doc(hidden)]
505#[allow(clippy::used_underscore_binding)] pub fn legacy_fused_core_kernel(
507 _clock_reset: ClockReset,
508 input: LegacyCoreInput,
509 q: Q,
510) -> (LegacyFusedOutput, D) {
511 let mut d = D::dont_care();
512 let mut control = q.control;
513 let mut data = q.data;
514 d.keccak = IterativeInput::default();
515
516 control.computed_done = false;
517 control.credit_release = false;
518
519 let start_ready = !q.control.active && !q.control.result_valid && input.output_credit_available;
520
521 if start_ready && input.start_valid {
522 control.active = true;
523 control.waiting = false;
524 control.credit_reserved = true;
525 control.result_valid = false;
526 control.audit_error = false;
527 control.from_private_seed = input.from_private_seed;
528 if input.from_private_seed {
529 control.phase = b3(PHASE_PRIVATE_SEED);
530 } else {
531 control.phase = b3(PHASE_PUBLIC_SEED);
532 }
533 control.mask_index = b5(0);
534 control.segment = b7(0);
535 control.chain_step = b4(0);
536 control.public_key_block = b5(0);
537 control.output_beat = b6(0);
538 control.permutation_count = b11(0);
539 if input.from_private_seed {
540 data.private_seed = legacy_bytes_to_lanes_kernel(input.secret);
541 data.private_key = [b64(0); 4];
542 } else {
543 data.private_seed = [b64(0); 4];
544 data.private_key = legacy_bytes_to_lanes_kernel(input.secret);
545 }
546 data.message_digits = message_digits_kernel(input.message);
547 data.public_seed = [b64(0); 4];
548 data.masks = [[b64(0); 4]; LEGACY_MASK_COUNT];
549 data.signature = [[b64(0); 4]; CHAIN_COUNT];
550 data.endpoints = [[b64(0); 4]; CHAIN_COUNT];
551 data.secret_prf = [b64(0); 4];
552 data.chain_state = [b64(0); 4];
553 data.public_key_sponge = [b64(0); 25];
554 data.public_key_hash = [b64(0); 4];
555 } else if q.control.active {
556 if q.control.waiting {
557 if q.keccak.done {
558 let digest = legacy_digest_lanes_kernel(q.keccak.state);
559 control.waiting = false;
560 control.permutation_count = q.control.permutation_count + b11(1);
561
562 match q.control.phase {
563 Bits::<3>(0) => {
564 data.private_key = digest;
565 control.phase = b3(PHASE_PUBLIC_SEED);
566 }
567 Bits::<3>(1) => {
568 data.public_seed = digest;
569 control.phase = b3(PHASE_MASK);
570 control.mask_index = b5(0);
571 }
572 Bits::<3>(2) => {
573 data.masks[q.control.mask_index] = digest;
574 if q.control.mask_index == b5(15) {
575 control.phase = b3(PHASE_SEGMENT_PRF);
576 control.segment = b7(0);
577 } else {
578 control.mask_index = q.control.mask_index + b5(1);
579 }
580 }
581 Bits::<3>(3) => {
582 data.secret_prf = digest;
583 control.phase = b3(PHASE_SECRET_HASH);
584 }
585 Bits::<3>(4) => {
586 data.chain_state = digest;
587 if q.data.message_digits[q.control.segment] == b4(0) {
588 data.signature[q.control.segment] = digest;
589 }
590 control.phase = b3(PHASE_CHAIN);
591 control.chain_step = b4(1);
592 }
593 Bits::<3>(5) => {
594 data.chain_state = digest;
595 if q.data.message_digits[q.control.segment] == q.control.chain_step {
596 data.signature[q.control.segment] = digest;
597 }
598 if q.control.chain_step == b4(15) {
599 data.endpoints[q.control.segment] = digest;
600 if q.control.segment == b7(66) {
601 data.private_key = [b64(0); 4];
603 data.secret_prf = [b64(0); 4];
604 data.chain_state = [b64(0); 4];
605 control.phase = b3(PHASE_PUBLIC_KEY);
606 control.public_key_block = b5(0);
607 data.public_key_sponge = [b64(0); 25];
608 } else {
609 control.segment = q.control.segment + b7(1);
610 control.phase = b3(PHASE_SEGMENT_PRF);
611 }
612 } else {
613 control.chain_step = q.control.chain_step + b4(1);
614 }
615 }
616 _ => {
617 data.public_key_sponge = q.keccak.state;
618 if q.control.public_key_block == b5(15) {
619 data.public_key_hash = digest;
620 control.active = false;
621 control.result_valid = true;
622 control.computed_done = true;
623 if q.control.from_private_seed {
624 control.audit_error = q.control.permutation_count != b11(1_172);
625 } else {
626 control.audit_error = q.control.permutation_count != b11(1_171);
627 }
628 control.output_beat = b6(0);
629 } else {
630 control.public_key_block = q.control.public_key_block + b5(1);
631 }
632 }
633 }
634 }
635 } else if q.keccak.ready {
636 let mut request_state = legacy_hash32_state_kernel(q.data.private_seed);
637 match q.control.phase {
638 Bits::<3>(0) => {
639 data.private_seed = [b64(0); 4];
641 }
642 Bits::<3>(1) => {
643 request_state = legacy_prf_state_kernel(LegacyPrfStateInput {
644 seed: q.data.private_key,
645 index: b16(0),
646 });
647 }
648 Bits::<3>(2) => {
649 request_state = legacy_prf_state_kernel(LegacyPrfStateInput {
650 seed: q.data.public_seed,
651 index: q.control.mask_index.resize(),
652 });
653 }
654 Bits::<3>(3) => {
655 let segment_index: b16 = q.control.segment.resize();
656 request_state = legacy_prf_state_kernel(LegacyPrfStateInput {
657 seed: q.data.private_key,
658 index: segment_index + b16(1),
659 });
660 }
661 Bits::<3>(4) => {
662 request_state = legacy_secret_state_kernel(LegacySecretStateInput {
663 function_key: q.data.masks[0],
664 secret_prf: q.data.secret_prf,
665 });
666 }
667 Bits::<3>(5) => {
668 request_state = legacy_chain_state_kernel(LegacyChainStateInput {
669 state: q.data.chain_state,
670 mask: q.data.masks[q.control.chain_step],
671 });
672 }
673 _ => {
674 request_state = legacy_endpoint_block_state_kernel(LegacyEndpointBlockInput {
675 sponge: q.data.public_key_sponge,
676 endpoints: q.data.endpoints,
677 block_index: q.control.public_key_block,
678 });
679 }
680 }
681 d.keccak = IterativeInput {
682 start: true,
683 state: request_state,
684 };
685 control.waiting = true;
686 }
687 } else if q.control.result_valid && input.output_ready {
688 if q.control.output_beat == b6(FINAL_OUTPUT_BEAT) {
689 control.result_valid = false;
690 control.credit_reserved = false;
691 control.credit_release = true;
692 control.output_beat = b6(0);
693 control.permutation_count = b11(0);
694 data.public_seed = [b64(0); 4];
696 data.public_key_hash = [b64(0); 4];
697 data.signature = [[b64(0); 4]; CHAIN_COUNT];
698 data.endpoints = [[b64(0); 4]; CHAIN_COUNT];
699 data.masks = [[b64(0); 4]; LEGACY_MASK_COUNT];
700 } else {
701 control.output_beat = q.control.output_beat + b6(1);
702 }
703 }
704
705 let mut output_beat = LegacyFusedBeat {
706 data: [b8(0); 64],
707 keep: b64(0),
708 last: false,
709 };
710 if q.control.result_valid {
711 output_beat = legacy_output_beat_kernel(LegacyOutputBeatInput {
712 signature: q.data.signature,
713 public_seed: q.data.public_seed,
714 public_key_hash: q.data.public_key_hash,
715 beat_index: q.control.output_beat,
716 });
717 }
718
719 d.control = control;
720 d.data = data;
721 let output = LegacyFusedOutput {
722 start_ready,
723 active: q.control.active,
724 output_credit_reserved: q.control.credit_reserved,
725 output_valid: q.control.result_valid,
726 output: output_beat,
727 computed_done: q.control.computed_done,
728 output_credit_release: q.control.credit_release,
729 permutation_count: q.control.permutation_count,
730 audit_error: q.control.audit_error,
731 };
732 (output, d)
733}
734
735mod seed_wrapper {
736 #[allow(clippy::wildcard_imports)] use super::*;
738
739 #[derive(Clone, Debug, Default, Synchronous, SynchronousDQ)]
752 #[rhdl(dq_no_prefix)]
753 pub struct LegacyFusedPrivateSeedEngine {
754 core: LegacyFusedCore,
755 }
756
757 impl SynchronousIO for LegacyFusedPrivateSeedEngine {
758 type I = LegacyFusedInput;
759 type O = LegacyFusedOutput;
760 type Kernel = legacy_fused_private_seed_kernel;
761 }
762
763 #[kernel]
765 #[allow(clippy::used_underscore_binding)] pub fn legacy_fused_private_seed_kernel(
767 _clock_reset: ClockReset,
768 input: LegacyFusedInput,
769 q: Q,
770 ) -> (LegacyFusedOutput, D) {
771 let mut d = D::dont_care();
772 d.core = LegacyCoreInput {
773 start_valid: input.start_valid,
774 secret: input.private_seed,
775 message: input.message,
776 output_credit_available: input.output_credit_available,
777 output_ready: input.output_ready,
778 from_private_seed: true,
779 };
780 (q.core, d)
781 }
782}
783
784pub use seed_wrapper::{LegacyFusedPrivateSeedEngine, legacy_fused_private_seed_kernel};
785
786mod key_wrapper {
787 #[allow(clippy::wildcard_imports)] use super::*;
789
790 #[derive(Clone, Debug, Default, Synchronous, SynchronousDQ)]
798 #[rhdl(dq_no_prefix)]
799 pub struct LegacyFusedPrivateKeyEngine {
800 core: LegacyFusedCore,
801 }
802
803 impl SynchronousIO for LegacyFusedPrivateKeyEngine {
804 type I = LegacyFusedPrivateKeyInput;
805 type O = LegacyFusedOutput;
806 type Kernel = legacy_fused_private_key_kernel;
807 }
808
809 #[kernel]
811 #[allow(clippy::used_underscore_binding)] pub fn legacy_fused_private_key_kernel(
813 _clock_reset: ClockReset,
814 input: LegacyFusedPrivateKeyInput,
815 q: Q,
816 ) -> (LegacyFusedOutput, D) {
817 let mut d = D::dont_care();
818 d.core = LegacyCoreInput {
819 start_valid: input.start_valid,
820 secret: input.private_key,
821 message: input.message,
822 output_credit_available: input.output_credit_available,
823 output_ready: input.output_ready,
824 from_private_seed: false,
825 };
826 (q.core, d)
827 }
828}
829
830pub use key_wrapper::{LegacyFusedPrivateKeyEngine, legacy_fused_private_key_kernel};