tss_esapi/structures/tagged/
signature.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    interface_types::algorithm::SignatureSchemeAlgorithm,
5    structures::{EccSignature, HashAgile, RsaSignature},
6    traits::{Marshall, UnMarshall},
7    tss2_esys::{TPMT_SIGNATURE, TPMU_SIGNATURE},
8    Error, Result, WrapperErrorKind,
9};
10use log::error;
11use std::{
12    convert::{TryFrom, TryInto},
13    mem::size_of,
14};
15use tss_esapi_sys::{Tss2_MU_TPMT_SIGNATURE_Marshal, Tss2_MU_TPMT_SIGNATURE_Unmarshal};
16
17/// Enum representing a Signature
18///
19/// # Details
20/// This corresponds TPMT_SIGNATURE
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum Signature {
23    RsaSsa(RsaSignature),
24    RsaPss(RsaSignature),
25    EcDsa(EccSignature),
26    EcDaa(EccSignature),
27    Sm2(EccSignature),
28    EcSchnorr(EccSignature),
29    Hmac(HashAgile),
30    Null,
31}
32
33impl Signature {
34    pub fn algorithm(&self) -> SignatureSchemeAlgorithm {
35        match self {
36            Signature::RsaSsa(_) => SignatureSchemeAlgorithm::RsaSsa,
37            Signature::RsaPss(_) => SignatureSchemeAlgorithm::RsaPss,
38            Signature::EcDsa(_) => SignatureSchemeAlgorithm::EcDsa,
39            Signature::EcDaa(_) => SignatureSchemeAlgorithm::EcDaa,
40            Signature::Sm2(_) => SignatureSchemeAlgorithm::Sm2,
41            Signature::EcSchnorr(_) => SignatureSchemeAlgorithm::EcSchnorr,
42            Signature::Hmac(_) => SignatureSchemeAlgorithm::Hmac,
43            Signature::Null => SignatureSchemeAlgorithm::Null,
44        }
45    }
46}
47
48impl TryFrom<Signature> for TPMT_SIGNATURE {
49    type Error = Error;
50
51    fn try_from(signature: Signature) -> Result<Self> {
52        let signature_algorithm = signature.algorithm().into();
53        match signature {
54            Signature::RsaSsa(rsa_signature) => Ok(TPMT_SIGNATURE {
55                sigAlg: signature_algorithm,
56                signature: TPMU_SIGNATURE {
57                    rsassa: rsa_signature.into(),
58                },
59            }),
60            Signature::RsaPss(rsa_signature) => Ok(TPMT_SIGNATURE {
61                sigAlg: signature_algorithm,
62                signature: TPMU_SIGNATURE {
63                    rsapss: rsa_signature.into(),
64                },
65            }),
66            Signature::EcDsa(ecc_signature) => Ok(TPMT_SIGNATURE {
67                sigAlg: signature_algorithm,
68                signature: TPMU_SIGNATURE {
69                    ecdsa: ecc_signature.into(),
70                },
71            }),
72            Signature::EcDaa(ecc_signature) => Ok(TPMT_SIGNATURE {
73                sigAlg: signature_algorithm,
74                signature: TPMU_SIGNATURE {
75                    ecdaa: ecc_signature.into(),
76                },
77            }),
78            Signature::Sm2(ecc_signature) => Ok(TPMT_SIGNATURE {
79                sigAlg: signature_algorithm,
80                signature: TPMU_SIGNATURE {
81                    sm2: ecc_signature.into(),
82                },
83            }),
84            Signature::EcSchnorr(ecc_signature) => Ok(TPMT_SIGNATURE {
85                sigAlg: signature_algorithm,
86                signature: TPMU_SIGNATURE {
87                    ecschnorr: ecc_signature.into(),
88                },
89            }),
90            Signature::Hmac(hash_agile) => Ok(TPMT_SIGNATURE {
91                sigAlg: signature_algorithm,
92                signature: TPMU_SIGNATURE {
93                    hmac: hash_agile.try_into()?,
94                },
95            }),
96            Signature::Null => Ok(TPMT_SIGNATURE {
97                sigAlg: signature_algorithm,
98                signature: Default::default(),
99            }),
100        }
101    }
102}
103
104impl TryFrom<TPMT_SIGNATURE> for Signature {
105    type Error = Error;
106
107    fn try_from(tpmt_signature: TPMT_SIGNATURE) -> Result<Self> {
108        match SignatureSchemeAlgorithm::try_from(tpmt_signature.sigAlg)? {
109            SignatureSchemeAlgorithm::RsaSsa => Ok(Signature::RsaSsa(
110                unsafe { tpmt_signature.signature.rsassa }.try_into()?,
111            )),
112            SignatureSchemeAlgorithm::RsaPss => Ok(Signature::RsaPss(
113                unsafe { tpmt_signature.signature.rsapss }.try_into()?,
114            )),
115            SignatureSchemeAlgorithm::EcDsa => Ok(Signature::EcDsa(
116                unsafe { tpmt_signature.signature.ecdsa }.try_into()?,
117            )),
118            SignatureSchemeAlgorithm::EcDaa => Ok(Signature::EcDaa(
119                unsafe { tpmt_signature.signature.ecdaa }.try_into()?,
120            )),
121            SignatureSchemeAlgorithm::Sm2 => Ok(Signature::Sm2(
122                unsafe { tpmt_signature.signature.sm2 }.try_into()?,
123            )),
124            SignatureSchemeAlgorithm::EcSchnorr => Ok(Signature::EcSchnorr(
125                unsafe { tpmt_signature.signature.ecschnorr }.try_into()?,
126            )),
127            SignatureSchemeAlgorithm::Hmac => Ok(Signature::Hmac(
128                unsafe { tpmt_signature.signature.hmac }.try_into()?,
129            )),
130            SignatureSchemeAlgorithm::Null => Ok(Signature::Null),
131        }
132    }
133}
134
135impl Marshall for Signature {
136    #[allow(unused_qualifications)]
137    const BUFFER_SIZE: usize = size_of::<TPMT_SIGNATURE>();
138
139    /// Produce a marshalled [`TPMT_SIGNATURE`]
140    fn marshall(&self) -> Result<Vec<u8>> {
141        let tpmt_sig = TPMT_SIGNATURE::try_from(self.clone())?;
142        let mut offset = 0;
143        let mut buffer = vec![0; Self::BUFFER_SIZE];
144
145        let ret = unsafe {
146            Tss2_MU_TPMT_SIGNATURE_Marshal(
147                &tpmt_sig,
148                buffer.as_mut_ptr(),
149                buffer.capacity().try_into().map_err(|e| {
150                    error!("Failed to convert size of buffer to TSS size_t type: {}", e);
151                    Error::local_error(WrapperErrorKind::InvalidParam)
152                })?,
153                &mut offset,
154            )
155        };
156        let ret = Error::from_tss_rc(ret);
157        if ret.is_success() {
158            let checked_offset = usize::try_from(offset).map_err(|e| {
159                error!("Failed to parse offset as usize: {}", e);
160                Error::local_error(WrapperErrorKind::InvalidParam)
161            })?;
162
163            buffer.truncate(checked_offset);
164            Ok(buffer)
165        } else {
166            Err(ret)
167        }
168    }
169}
170
171impl UnMarshall for Signature {
172    /// Unmarshall the structure from [`TPMT_SIGNATURE`]
173    fn unmarshall(public_buffer: &[u8]) -> Result<Self> {
174        let mut tpmt_sig = TPMT_SIGNATURE::default();
175        let mut offset = 0;
176
177        let ret = unsafe {
178            Tss2_MU_TPMT_SIGNATURE_Unmarshal(
179                public_buffer.as_ptr(),
180                public_buffer.len().try_into().map_err(|e| {
181                    error!("Failed to convert length of marshalled data: {}", e);
182                    Error::local_error(WrapperErrorKind::InvalidParam)
183                })?,
184                &mut offset,
185                &mut tpmt_sig,
186            )
187        };
188        let ret = Error::from_tss_rc(ret);
189        if ret.is_success() {
190            Ok(tpmt_sig.try_into()?)
191        } else {
192            Err(ret)
193        }
194    }
195}