1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::{DerVec, SignatureVerificationRequest, TbsCertificate, Validity};
use sp_core::U256;
use std::sync::Arc;
use x509_parser::der_parser::asn1_rs::BitString;
use x509_parser::prelude::{AlgorithmIdentifier, FromDer, SubjectPublicKeyInfo};

/// Host function trait for Certificate registration
pub trait HostFunctions: Send + Sync {
    fn verify_signature(&self, req: SignatureVerificationRequest) -> Option<()>;
    fn decode_tbs_certificate(&self, certificate: DerVec) -> Option<TbsCertificate>;
}

sp_externalities::decl_extension! {
    pub struct HostFunctionExtension(Arc<dyn HostFunctions>);
}

impl HostFunctionExtension {
    /// Create a new instance of [`HostFunctionExtension`].
    pub fn new(inner: Arc<dyn HostFunctions>) -> Self {
        Self(inner)
    }
}

/// Implementation of host functions for Certificate registry.
#[derive(Default)]
pub struct HostFunctionsImpl;

impl HostFunctions for HostFunctionsImpl {
    fn verify_signature(&self, req: SignatureVerificationRequest) -> Option<()> {
        verify_signature(req)
    }

    fn decode_tbs_certificate(&self, certificate: DerVec) -> Option<TbsCertificate> {
        decode_tbs_certificate(certificate)
    }
}

pub(crate) fn decode_tbs_certificate(certificate: DerVec) -> Option<TbsCertificate> {
    let (_, tbs_certificate) =
        x509_parser::certificate::TbsCertificate::from_der(certificate.as_ref()).ok()?;
    let serial = U256::from_big_endian(&tbs_certificate.serial.to_bytes_be());
    let validity = Validity::try_from(tbs_certificate.validity).ok()?;
    let subject_common_name = tbs_certificate
        .subject
        .iter_common_name()
        .next()
        .map(|cn| cn.attr_value().as_bytes().to_vec())?;

    Some(TbsCertificate {
        serial,
        subject_common_name,
        subject_public_key_info: tbs_certificate.subject_pki.raw.to_vec().into(),
        validity,
    })
}

pub(crate) fn verify_signature(req: SignatureVerificationRequest) -> Option<()> {
    let SignatureVerificationRequest {
        public_key_info,
        signature_algorithm,
        data,
        signature,
    } = req;

    let (_, public_key_info) = SubjectPublicKeyInfo::from_der(public_key_info.as_ref()).ok()?;
    let (_, signature_algorithm) =
        AlgorithmIdentifier::from_der(signature_algorithm.as_ref()).ok()?;
    let signature = BitString::new(0, &signature);
    x509_parser::verify::verify_signature(&public_key_info, &signature_algorithm, &signature, &data)
        .ok()
}