Skip to main content

csv_rs/certs/ca/cert/
mod.rs

1// Copyright (C) Hygon Info Technologies Ltd.
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! Operations that can be done on a Certificate Authority chain.
6
7use crate::{
8    certs::{Algorithm, Usage, Verifiable},
9    crypto::{key::ecc, sig::ecdsa, PublicKey, Signature},
10    util::*,
11};
12
13use serde::{Deserialize, Serialize};
14use serde_big_array::BigArray;
15use std::io::{Error, ErrorKind, Read, Result, Write};
16
17#[repr(C)]
18#[derive(Copy, Clone, Serialize, Deserialize)]
19pub struct Data {
20    pub kid: [u8; 16],
21    pub sid: [u8; 16],
22    pub usage: Usage,
23    pub reserved: [u8; 24],
24}
25
26#[repr(C)]
27#[derive(Copy, Clone, Serialize, Deserialize)]
28pub struct Preamble {
29    pub ver: u32,
30    pub data: Data,
31}
32
33#[repr(C)]
34#[derive(Copy, Clone, Serialize, Deserialize)]
35pub struct Body {
36    pub preamble: Preamble,
37    pub pubkey: ecc::PubKey,
38    pub uid_size: u16,
39    #[serde(with = "BigArray")]
40    pub user_id: [u8; 254],
41    #[serde(with = "BigArray")]
42    pub reserved: [u8; 108],
43}
44
45/// A Certificate Authority chain.
46#[repr(C)]
47#[derive(Copy, Clone, Serialize, Deserialize)]
48pub struct Certificate {
49    pub body: Body,
50    signature: ecdsa::Signature,
51    #[serde(with = "BigArray")]
52    _reserved: [u8; 112],
53}
54
55impl Certificate {
56    /// Writes the certificate content to a file.
57    pub fn write_to_file(&self, path: &std::path::Path) -> Result<()> {
58        let mut file = std::fs::File::create(path)?;
59        let encoded = bincode::serialize(self).map_err(|e| Error::new(ErrorKind::Other, e))?;
60        file.write_all(&encoded)?;
61        Ok(())
62    }
63}
64
65impl TryFrom<&Certificate> for Signature {
66    type Error = Error;
67
68    #[inline]
69    fn try_from(value: &Certificate) -> Result<Self> {
70        let sig = Vec::try_from(&value.signature)?;
71        Ok(Self {
72            sig,
73            id: Some(value.body.preamble.data.sid),
74            usage: Usage::HRK,
75            algo: None,
76        })
77    }
78}
79
80impl TryFrom<&Certificate> for PublicKey {
81    type Error = Error;
82
83    #[inline]
84    fn try_from(value: &Certificate) -> Result<Self> {
85        let key = value.body.pubkey;
86        Ok(Self {
87            id: Some(value.body.preamble.data.kid),
88            key,
89            usage: value.body.preamble.data.usage,
90            algo: Some(Algorithm::SM2_SA),
91        })
92    }
93}
94
95impl TryFrom<&Certificate> for Usage {
96    type Error = Error;
97
98    fn try_from(value: &Certificate) -> Result<Self> {
99        Ok(value.body.preamble.data.usage)
100    }
101}
102
103impl codicon::Decoder<()> for Certificate {
104    type Error = Error;
105
106    fn decode(mut reader: impl Read, _: ()) -> Result<Self> {
107        Ok(Self {
108            body: reader.load()?,
109            signature: reader.load()?,
110            _reserved: reader.load()?,
111        })
112    }
113}
114
115impl codicon::Encoder<crate::Body> for Certificate {
116    type Error = Error;
117
118    fn encode(&self, mut writer: impl Write, _: crate::Body) -> Result<()> {
119        writer.save(&self.body)
120    }
121}
122
123impl Verifiable for (&Certificate, &Certificate) {
124    type Output = ();
125
126    fn verify(self) -> Result<()> {
127        let key: PublicKey = self.0.try_into()?;
128        let sig: Signature = self.1.try_into()?;
129        key.verify(
130            self.1,
131            &self.0.body.user_id[..self.0.body.uid_size as usize],
132            &sig,
133        )
134    }
135}