rhdl_ubft/crypto/
ed25519.rs1use rhdl::prelude::*;
12use rhdl_ed25519_scalable_core::ubft::{self as svc, UbftEd25519, beat_words, words_beat};
13
14use crate::ports::{AxiLiteOut, Axis64, Axis512, CryptoIn, CryptoOut, CryptoScheme};
15use crate::setup::{ED25519_MAP, Setup, SetupIn};
16
17#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
19pub struct Ed25519Crypto<const NV: usize> {
20 setup: Setup,
21 service: UbftEd25519<1, NV>,
22 ready: rhdl_fpga::core::dff::DFF<bool>,
23 framing: rhdl_fpga::core::dff::DFF<bool>,
27}
28
29impl<const NV: usize> Default for Ed25519Crypto<NV> {
30 fn default() -> Self {
31 Self { setup: Setup::default(), service: UbftEd25519::default(), ready: rhdl_fpga::core::dff::DFF::new(false), framing: rhdl_fpga::core::dff::DFF::new(false) }
32 }
33}
34
35impl<const NV: usize> CryptoScheme for Ed25519Crypto<NV> {
36 const SHARE_BEATS: usize = 1;
37 const SCHEME: u8 = 1;
38}
39
40impl<const NV: usize> SynchronousIO for Ed25519Crypto<NV> {
41 type I = CryptoIn;
42 type O = CryptoOut;
43 type Kernel = ed25519_crypto_kernel<NV>;
44}
45
46#[kernel]
48pub fn to_service(b: Axis512) -> svc::Axis512 {
49 svc::Axis512 { valid: b.valid, data: words_beat(b.data), last: b.last }
50}
51
52#[kernel]
54pub fn from_service(b: svc::Axis512) -> Axis512 {
55 Axis512 { valid: b.valid, data: beat_words(b.data), keep: !b64(0), last: b.last }
56}
57
58#[kernel]
62pub fn frame_errors(sign: Axis512, verify: Axis512) -> (bool, bool) {
63 let sign_bad = sign.valid && (!sign.last || sign.keep != !b64(0));
64 let verify_bad = verify.valid && verify.keep != !b64(0);
65 (sign_bad, verify_bad)
66}
67
68#[kernel]
70pub fn ed25519_crypto_kernel<const NV: usize>(
71 _cr: ClockReset,
72 i: CryptoIn,
73 q: Ed25519CryptoQ<NV>,
74) -> (CryptoOut, Ed25519CryptoD<NV>) {
75 let su = q.setup;
76 let sv = q.service;
77 let mut d = Ed25519CryptoD::<NV>::dont_care();
79 d.setup = SetupIn {
80 start: i.setup,
81 map: ED25519_MAP,
82 n: i.n,
83 sk: i.sk,
84 keys_base: i.keys_base,
85 svc: AxiLiteOut {
86 aw_ready: sv.axi.aw_ready,
87 w_ready: sv.axi.w_ready,
88 b_valid: sv.axi.b_valid,
89 b_resp: sv.axi.b_resp,
90 ar_ready: sv.axi.ar_ready,
91 r_valid: sv.axi.r_valid,
92 r_data: sv.axi.r_data,
93 r_resp: sv.axi.r_resp,
94 interrupt: sv.axi.interrupt,
95 },
96 msg: i.msg,
97 };
98 let (sign_bad, verify_bad) = frame_errors(i.sign, i.verify);
103 let framing = q.framing || sign_bad || verify_bad;
104 d.framing = framing;
105 if i.setup {
106 d.framing = false;
107 }
108 let pass = !framing;
109 let mut sign_in = to_service(i.sign);
110 sign_in.valid = i.sign.valid && pass;
111 let mut verify_in = to_service(i.verify);
112 verify_in.valid = i.verify.valid && pass;
113 let a = su.svc;
114 d.service = svc::UbftIn {
115 axi: svc::AxiLiteIn {
116 aw_valid: a.aw_valid,
117 aw_addr: a.aw_addr,
118 w_valid: a.w_valid,
119 w_data: a.w_data,
120 w_strb: a.w_strb,
121 b_ready: a.b_ready,
122 ar_valid: false,
123 ar_addr: b12(0),
124 r_ready: true,
125 },
126 sign: sign_in,
127 sig_ready: i.sig_ready,
128 verify: verify_in,
129 verdict_ready: i.verdict_ready,
130 };
131 let mut ready = q.ready;
132 if i.setup {
133 ready = false;
134 }
135 if su.done {
136 ready = true;
137 }
138 d.ready = ready;
139 let o = CryptoOut {
140 ready: q.ready,
141 msg: su.msg,
142 sign_ready: sv.sign_ready || !pass,
145 sig: from_service(sv.sig),
146 verify_ready: sv.verify_ready || !pass,
147 verdict: Axis64 { valid: sv.verdict.valid, data: sv.verdict.data },
148 fault: q.framing,
149 announce: Axis512 { valid: false, data: [b64(0); 8], keep: b64(0), last: false },
150 cert_ready: true,
151 };
152 (o, d)
153}