1pub mod key;
8
9use crate::{
10 certs::{ca, Algorithm, Signer, Usage, Verifiable},
11 crypto::{self, key::ecc, sig::ecdsa, sm, PrivateKey, PublicKey, Signature},
12 util::*,
13};
14use serde::{Deserialize, Serialize};
15use serde_big_array::BigArray;
16use std::io::{Error, ErrorKind, Read, Result, Write};
17
18#[repr(C)]
19#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
20pub struct Data {
21 pub firmware: crate::Version,
22 pub reserved1: u16,
23 pub pubkey: key::PubKey,
24 pub uid_size: u16,
25 #[serde(with = "BigArray")]
26 pub user_id: [u8; 254],
27 pub sid: [u8; 16],
28 #[serde(with = "BigArray")]
29 pub reserved2: [u8; 608],
30}
31
32#[repr(C)]
33#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
34pub struct Body {
35 pub ver: u32,
36 pub data: Data,
37}
38
39#[repr(C)]
40#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
41pub struct Signatures {
42 usage: Usage,
43 algo: Algorithm,
44 signature: ecdsa::Signature,
45 #[serde(with = "BigArray")]
46 _reserved: [u8; 368],
47}
48
49impl Default for Signatures {
50 fn default() -> Self {
51 let _reserved = [0u8; 368];
52 Signatures {
53 usage: Usage::INV,
54 algo: Algorithm::NONE,
55 signature: ecdsa::Signature::default(),
56 _reserved,
57 }
58 }
59}
60
61impl TryFrom<&crypto::Signature> for Signatures {
62 type Error = Error;
63
64 #[inline]
65 fn try_from(value: &crypto::Signature) -> Result<Self> {
66 let algo = value.algo.unwrap_or(Algorithm::NONE);
67 Ok(Signatures {
68 usage: value.usage,
69 algo,
70 signature: ecdsa::Signature::try_from(&value.sig[..])?,
71 _reserved: [0u8; 368],
72 })
73 }
74}
75
76#[repr(C)]
77#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
78pub struct Certificate {
79 pub body: Body,
80 pub sigs: [Signatures; 2],
81}
82
83impl Certificate {
84 pub fn write_to_file(&self, path: &std::path::Path) -> Result<()> {
86 let mut file = std::fs::File::create(path)?;
87 let encoded = bincode::serialize(self).map_err(|e| Error::new(ErrorKind::Other, e))?;
88 file.write_all(&encoded)?;
89 Ok(())
90 }
91}
92
93impl TryFrom<&Signatures> for Option<Signature> {
94 type Error = Error;
95
96 #[inline]
97 fn try_from(value: &Signatures) -> Result<Self> {
98 if value.is_empty() {
99 return Ok(None);
100 }
101
102 let usage = value.usage;
103 let algo = value.algo;
104 let sig = Vec::try_from(&value.signature)?;
105 Ok(Some(Signature {
106 sig,
107 usage,
108 algo: Some(algo),
109 id: None,
110 }))
111 }
112}
113
114impl TryFrom<&Certificate> for [Option<Signature>; 2] {
115 type Error = Error;
116
117 #[inline]
118 fn try_from(value: &Certificate) -> Result<Self> {
119 Ok([(&value.sigs[0]).try_into()?, (&value.sigs[1]).try_into()?])
120 }
121}
122
123impl TryFrom<&Certificate> for PublicKey {
124 type Error = Error;
125
126 fn try_from(value: &Certificate) -> Result<Self> {
127 let key = value.body.data.pubkey.key;
128 Ok(Self {
129 id: None,
130 key,
131 usage: value.body.data.pubkey.usage,
132 algo: Some(value.body.data.pubkey.algo),
133 })
134 }
135}
136
137impl Signer<Certificate> for PrivateKey<Usage> {
138 type Output = ();
139
140 fn sign(&self, target: &mut Certificate, uid: String) -> Result<()> {
141 let slot = if target.sigs[0].is_empty() {
142 &mut target.sigs[0]
143 } else if target.sigs[1].is_empty() {
144 &mut target.sigs[1]
145 } else {
146 return Err(ErrorKind::InvalidInput.into());
147 };
148
149 let mut msg: Vec<u8> = Vec::new();
150 msg.save(&target.body)?;
151
152 let sig = sm::SM2::sign(self.key, uid.as_bytes(), &msg)?;
153
154 let sig = crate::crypto::Signature {
155 usage: self.usage,
156 sig,
157 algo: Some(self.usage.try_into()?),
158 id: self.id,
159 };
160
161 *slot = Signatures::try_from(&sig)?;
162
163 Ok(())
164 }
165}
166
167impl Verifiable for (&Certificate, &Certificate) {
168 type Output = ();
169
170 fn verify(self) -> Result<()> {
171 let key: PublicKey = self.0.try_into()?;
172
173 let sigs: [Option<Signature>; 2] = self.1.try_into()?;
174 for sig in sigs.iter().flatten() {
175 if key
176 .verify(
177 self.1,
178 &self.0.body.data.user_id[..self.0.body.data.uid_size as usize],
179 sig,
180 )
181 .is_ok()
182 {
183 return Ok(());
184 }
185 }
186
187 Err(ErrorKind::InvalidInput.into())
188 }
189}
190
191impl Verifiable for (&ca::cert::Certificate, &Certificate) {
192 type Output = ();
193
194 fn verify(self) -> Result<()> {
195 let key: PublicKey = self.0.try_into()?;
196 let sigs: [Option<Signature>; 2] = self.1.try_into()?;
197 for sig in sigs.iter().flatten() {
198 if key
199 .verify(
200 self.1,
201 &self.0.body.user_id[..self.0.body.uid_size as usize],
202 sig,
203 )
204 .is_ok()
205 {
206 return Ok(());
207 }
208 }
209 Err(ErrorKind::InvalidInput.into())
210 }
211}
212
213impl codicon::Decoder<()> for Signatures {
214 type Error = Error;
215
216 #[inline]
217 fn decode(mut reader: impl Read, _: ()) -> Result<Self> {
218 let mut _reserved = [0u8; 368];
219 let usage: Usage = reader.load()?;
220 let algo: Algorithm = reader.load()?;
221 let signature: ecdsa::Signature = reader.load()?;
222 reader.read_exact(&mut _reserved)?;
223 Ok(Self {
224 usage,
225 algo,
226 signature,
227 _reserved,
228 })
229 }
230}
231
232impl codicon::Decoder<()> for Certificate {
233 type Error = Error;
234
235 fn decode(mut reader: impl Read, _: ()) -> Result<Self> {
236 let body: Body = reader.load()?;
237 let sig1 = Signatures::decode(&mut reader, ())?;
238 let sig2 = Signatures::decode(&mut reader, ())?;
239 Ok(Self {
240 body,
241 sigs: [sig1, sig2],
242 })
243 }
244}
245
246impl codicon::Encoder<crate::Body> for Certificate {
247 type Error = Error;
248
249 fn encode(&self, mut writer: impl Write, _: crate::Body) -> Result<()> {
250 writer.save(&self.body)
251 }
252}
253
254impl TryFrom<&Certificate> for Usage {
255 type Error = Error;
256
257 fn try_from(value: &Certificate) -> Result<Self> {
258 Ok(value.body.data.pubkey.usage)
259 }
260}
261
262impl Signatures {
263 pub fn is_empty(&self) -> bool {
264 match self.usage {
265 Usage::CEK | Usage::HRK | Usage::HSK | Usage::OCA | Usage::PDH | Usage::PEK => {
266 !matches!(self.algo, Algorithm::SM2_SA | Algorithm::SM2_DH)
267 }
268 _ => true,
269 }
270 }
271}
272
273impl Body {
274 pub fn generate(usage: Usage, uid: Option<String>) -> Result<(Body, PrivateKey<Usage>)> {
275 let uid: String = if let Some(value) = uid {
276 value
277 } else {
278 String::try_from(usage)?
279 };
280
281 let Ok(uid_size) = uid.len().try_into() else {
282 return Err(ErrorKind::InvalidInput.into());
283 };
284
285 let mut user_id_vec = Vec::from(uid.as_bytes());
286 user_id_vec.resize(254, 0);
287 let mut user_id: [u8; 254] = [0; 254];
288 user_id.copy_from_slice(&user_id_vec);
289 let (pubkey, prv) = key::PubKey::generate(usage, None)?;
290 Ok((
291 Body {
292 ver: 1u32.to_le(),
293 data: Data {
294 firmware: Default::default(),
295 reserved1: 0,
296 pubkey,
297 uid_size,
298 user_id,
299 sid: [0u8; 16],
300 reserved2: [0u8; 608],
301 },
302 },
303 prv,
304 ))
305 }
306}
307
308impl Certificate {
309 pub fn generate(usage: Usage, uid: Option<String>) -> Result<(Self, PrivateKey<Usage>)> {
311 let (body, prv) = Body::generate(usage, uid)?;
312 Ok((
313 Self {
314 body,
315 sigs: [Signatures::default(), Signatures::default()],
316 },
317 prv,
318 ))
319 }
320
321 pub fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
323 let key: PublicKey = self.try_into()?;
324 key.encrypt(data)
325 }
326}
327
328#[cfg(feature = "network")]
330pub async fn download_hskcek(
331 sn: &[u8],
332) -> std::result::Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
333 let chip_id = std::str::from_utf8(sn)?.trim_end_matches('\0');
335 let kds_url = format!("https://cert.hygon.cn/hsk_cek?snumber={chip_id}");
336 log::trace!("kds_url: {}", kds_url);
337 let response = reqwest::Client::new()
339 .get(&kds_url)
340 .header("User-Agent", "Reqwest")
341 .send()
342 .await?; let response_body = response.bytes().await?.to_vec();
346 Ok(response_body)
347}
348
349#[cfg(feature = "network")]
351pub async fn get_certificate_data(
352 chip_id: &[u8; 16],
353) -> std::result::Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
354 let cert_dir =
356 std::env::var("HSK_CEK_CERT_PATH").unwrap_or_else(|_| "/opt/dcu/certs".to_string());
357
358 let chip_id_str =
360 std::str::from_utf8(chip_id).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
361
362 let cert_path = format!("{}/{}_hsk_cek.cert", cert_dir, chip_id_str);
364
365 if tokio::fs::metadata(&cert_path).await.is_ok() {
367 log::debug!("Reading certificate from: {}", cert_path);
368 tokio::fs::read(cert_path).await.map_err(Into::into)
369 } else {
370 log::debug!(
371 "Certificate not found at {}, attempting download",
372 cert_path
373 );
374 download_hskcek(chip_id).await
375 }
376}