Skip to main content

tss_esapi/structures/tagged/
schemes.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    interface_types::algorithm::{
5        EccSchemeAlgorithm, HashingAlgorithm, KeyDerivationFunction, KeyedHashSchemeAlgorithm,
6        RsaDecryptAlgorithm, RsaSchemeAlgorithm, SignatureSchemeAlgorithm,
7    },
8    structures::schemes::{EcDaaScheme, HashScheme, HmacScheme, XorScheme},
9    tss2_esys::{
10        TPMT_ECC_SCHEME, TPMT_KDF_SCHEME, TPMT_KEYEDHASH_SCHEME, TPMT_RSA_DECRYPT, TPMT_RSA_SCHEME,
11        TPMT_SIG_SCHEME, TPMU_ASYM_SCHEME, TPMU_KDF_SCHEME, TPMU_SCHEME_KEYEDHASH, TPMU_SIG_SCHEME,
12    },
13    Error, Result, WrapperErrorKind,
14};
15use log::error;
16use std::convert::{TryFrom, TryInto};
17
18/// Enum representing the keyed hash scheme.
19///
20/// # Details
21/// This corresponds to TPMT_SCHEME_KEYEDHASH.
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum KeyedHashScheme {
24    Xor { xor_scheme: XorScheme },
25    Hmac { hmac_scheme: HmacScheme },
26    Null,
27}
28
29impl KeyedHashScheme {
30    pub const HMAC_SHA_256: KeyedHashScheme = KeyedHashScheme::Hmac {
31        hmac_scheme: HmacScheme::new(HashingAlgorithm::Sha256),
32    };
33}
34
35impl From<KeyedHashScheme> for TPMT_KEYEDHASH_SCHEME {
36    fn from(keyed_hash_scheme: KeyedHashScheme) -> Self {
37        match keyed_hash_scheme {
38            KeyedHashScheme::Xor { xor_scheme } => TPMT_KEYEDHASH_SCHEME {
39                scheme: KeyedHashSchemeAlgorithm::Xor.into(),
40                details: TPMU_SCHEME_KEYEDHASH {
41                    exclusiveOr: xor_scheme.into(),
42                },
43            },
44            KeyedHashScheme::Hmac { hmac_scheme } => TPMT_KEYEDHASH_SCHEME {
45                scheme: KeyedHashSchemeAlgorithm::Hmac.into(),
46                details: TPMU_SCHEME_KEYEDHASH {
47                    hmac: hmac_scheme.into(),
48                },
49            },
50            KeyedHashScheme::Null => TPMT_KEYEDHASH_SCHEME {
51                scheme: KeyedHashSchemeAlgorithm::Null.into(),
52                details: Default::default(),
53            },
54        }
55    }
56}
57
58impl TryFrom<TPMT_KEYEDHASH_SCHEME> for KeyedHashScheme {
59    type Error = Error;
60    fn try_from(tpmt_keyedhash_scheme: TPMT_KEYEDHASH_SCHEME) -> Result<KeyedHashScheme> {
61        match KeyedHashSchemeAlgorithm::try_from(tpmt_keyedhash_scheme.scheme)? {
62            KeyedHashSchemeAlgorithm::Xor => Ok(KeyedHashScheme::Xor {
63                xor_scheme: unsafe { tpmt_keyedhash_scheme.details.exclusiveOr }.try_into()?,
64            }),
65            KeyedHashSchemeAlgorithm::Hmac => Ok(KeyedHashScheme::Hmac {
66                hmac_scheme: unsafe { tpmt_keyedhash_scheme.details.hmac }.try_into()?,
67            }),
68            KeyedHashSchemeAlgorithm::Null => Ok(KeyedHashScheme::Null),
69        }
70    }
71}
72
73/// Enum representing the rsa scheme
74///
75/// # Details
76/// This corresponds to TPMT_RSA_SCHEME.
77/// This uses a subset of the TPMU_ASYM_SCHEME
78/// that has the TPMI_ALG_RSA_SCHEME as selector.
79#[derive(Clone, Copy, Debug, PartialEq, Eq)]
80pub enum RsaScheme {
81    RsaSsa(HashScheme),
82    RsaEs,
83    RsaPss(HashScheme),
84    Oaep(HashScheme),
85    Null,
86}
87
88impl RsaScheme {
89    /// Creates a new RsaScheme
90    ///
91    /// # Errors
92    /// - `InconsistentParams` error will be returned if no hashing algorithm
93    ///   is provided when creating RSA scheme of type RSA SSA, RSA PSS and OAEP
94    ///   or if a hashing algorithm is provided when creating a RSA scheme
95    pub fn create(
96        rsa_scheme_algorithm: RsaSchemeAlgorithm,
97        hashing_algorithm: Option<HashingAlgorithm>,
98    ) -> Result<RsaScheme> {
99        match rsa_scheme_algorithm {
100            RsaSchemeAlgorithm::RsaSsa => Ok(RsaScheme::RsaSsa(HashScheme::new(
101                hashing_algorithm.ok_or_else(|| {
102                    error!(
103                        "Hashing algorithm is required when creating RSA scheme of type RSA SSA"
104                    );
105                    Error::local_error(WrapperErrorKind::InconsistentParams)
106                })?,
107            ))),
108            RsaSchemeAlgorithm::RsaEs => {
109                if hashing_algorithm.is_none() {
110                    Ok(RsaScheme::RsaEs)
111                } else {
112                    error!("A hashing algorithm shall not be provided when creating RSA scheme of type RSA ES");
113                    Err(Error::local_error(WrapperErrorKind::InconsistentParams))
114                }
115            }
116            RsaSchemeAlgorithm::RsaPss => Ok(RsaScheme::RsaPss(HashScheme::new(
117                hashing_algorithm.ok_or_else(|| {
118                    error!(
119                        "Hashing algorithm is required when creating RSA scheme of type RSA PSS"
120                    );
121                    Error::local_error(WrapperErrorKind::InconsistentParams)
122                })?,
123            ))),
124            RsaSchemeAlgorithm::Oaep => Ok(RsaScheme::Oaep(HashScheme::new(
125                hashing_algorithm.ok_or_else(|| {
126                    error!("Hashing algorithm is required when creating RSA scheme of type OAEP");
127                    Error::local_error(WrapperErrorKind::InconsistentParams)
128                })?,
129            ))),
130            RsaSchemeAlgorithm::Null => {
131                if hashing_algorithm.is_none() {
132                    Ok(RsaScheme::Null)
133                } else {
134                    error!("A hashing algorithm shall not be provided when creating RSA scheme of type Null");
135                    Err(Error::local_error(WrapperErrorKind::InconsistentParams))
136                }
137            }
138        }
139    }
140
141    /// Returns the rsa scheme algorithm
142    pub fn algorithm(&self) -> RsaSchemeAlgorithm {
143        match self {
144            RsaScheme::RsaSsa(_) => RsaSchemeAlgorithm::RsaSsa,
145            RsaScheme::RsaEs => RsaSchemeAlgorithm::RsaEs,
146            RsaScheme::RsaPss(_) => RsaSchemeAlgorithm::RsaPss,
147            RsaScheme::Oaep(_) => RsaSchemeAlgorithm::Oaep,
148            RsaScheme::Null => RsaSchemeAlgorithm::Null,
149        }
150    }
151}
152
153impl From<RsaScheme> for TPMT_RSA_SCHEME {
154    fn from(rsa_scheme: RsaScheme) -> Self {
155        match rsa_scheme {
156            RsaScheme::RsaSsa(hash_scheme) => TPMT_RSA_SCHEME {
157                scheme: rsa_scheme.algorithm().into(),
158                details: TPMU_ASYM_SCHEME {
159                    rsassa: hash_scheme.into(),
160                },
161            },
162            RsaScheme::RsaEs => TPMT_RSA_SCHEME {
163                scheme: rsa_scheme.algorithm().into(),
164                details: TPMU_ASYM_SCHEME {
165                    rsaes: Default::default(),
166                },
167            },
168            RsaScheme::RsaPss(hash_scheme) => TPMT_RSA_SCHEME {
169                scheme: rsa_scheme.algorithm().into(),
170                details: TPMU_ASYM_SCHEME {
171                    rsapss: hash_scheme.into(),
172                },
173            },
174            RsaScheme::Oaep(hash_scheme) => TPMT_RSA_SCHEME {
175                scheme: rsa_scheme.algorithm().into(),
176                details: TPMU_ASYM_SCHEME {
177                    oaep: hash_scheme.into(),
178                },
179            },
180            RsaScheme::Null => TPMT_RSA_SCHEME {
181                scheme: rsa_scheme.algorithm().into(),
182                details: Default::default(),
183            },
184        }
185    }
186}
187
188impl TryFrom<TPMT_RSA_SCHEME> for RsaScheme {
189    type Error = Error;
190
191    fn try_from(tpmt_rsa_scheme: TPMT_RSA_SCHEME) -> Result<Self> {
192        match RsaSchemeAlgorithm::try_from(tpmt_rsa_scheme.scheme)? {
193            RsaSchemeAlgorithm::RsaSsa => Ok(RsaScheme::RsaSsa(
194                unsafe { tpmt_rsa_scheme.details.rsassa }.try_into()?,
195            )),
196            RsaSchemeAlgorithm::RsaEs => Ok(RsaScheme::RsaEs),
197            RsaSchemeAlgorithm::RsaPss => Ok(RsaScheme::RsaPss(
198                unsafe { tpmt_rsa_scheme.details.rsapss }.try_into()?,
199            )),
200            RsaSchemeAlgorithm::Oaep => Ok(RsaScheme::Oaep(
201                unsafe { tpmt_rsa_scheme.details.oaep }.try_into()?,
202            )),
203            RsaSchemeAlgorithm::Null => Ok(RsaScheme::Null),
204        }
205    }
206}
207
208/// Enum representing the ecc scheme
209///
210/// # Details
211/// This corresponds to TPMT_ECC_SCHEME.
212/// This uses a subset of the TPMU_ASYM_SCHEME
213/// that has the TPMI_ALG_ECC_SCHEME as selector.
214#[derive(Clone, Copy, Debug, PartialEq, Eq)]
215pub enum EccScheme {
216    EcDsa(HashScheme),
217    EcDh(HashScheme),
218    EcDaa(EcDaaScheme),
219    Sm2(HashScheme),
220    EcSchnorr(HashScheme),
221    EcMqv(HashScheme),
222    Null,
223}
224
225impl EccScheme {
226    pub fn create(
227        ecc_scheme_algorithm: EccSchemeAlgorithm,
228        hashing_algorithm: Option<HashingAlgorithm>,
229        count: Option<u16>,
230    ) -> Result<Self> {
231        match ecc_scheme_algorithm {
232            EccSchemeAlgorithm::EcDsa => Ok(EccScheme::EcDsa(HashScheme::new(
233                hashing_algorithm.ok_or_else(|| {
234                    error!("Hashing algorithm is required when creating ECC scheme of type EC DSA");
235                    Error::local_error(WrapperErrorKind::ParamsMissing)
236                })?,
237            ))),
238            EccSchemeAlgorithm::EcDh => Ok(EccScheme::EcDh(HashScheme::new(
239                hashing_algorithm.ok_or_else(|| {
240                    error!("Hashing algorithm is required when creating ECC scheme of type EC DH");
241                    Error::local_error(WrapperErrorKind::ParamsMissing)
242                })?,
243            ))),
244            EccSchemeAlgorithm::EcDaa => Ok(EccScheme::EcDaa(EcDaaScheme::new(
245                hashing_algorithm.ok_or_else(|| {
246                    error!("Hashing algorithm is required when creating ECC scheme of type EC DAA");
247                    Error::local_error(WrapperErrorKind::ParamsMissing)
248                })?,
249                count.ok_or_else(|| {
250                    error!("Count is required when creating ECC scheme of type EC DAA");
251                    Error::local_error(WrapperErrorKind::ParamsMissing)
252                })?,
253            ))),
254            EccSchemeAlgorithm::Sm2 => Ok(EccScheme::Sm2(HashScheme::new(
255                hashing_algorithm.ok_or_else(|| {
256                    error!("Hashing algorithm is required when creating ECC scheme of type EC SM2");
257                    Error::local_error(WrapperErrorKind::ParamsMissing)
258                })?,
259            ))),
260            EccSchemeAlgorithm::EcSchnorr => Ok(EccScheme::EcSchnorr(HashScheme::new(
261                hashing_algorithm.ok_or_else(|| {
262                    error!(
263                        "Hashing algorithm is required when creating ECC scheme of type EC SCHNORR"
264                    );
265                    Error::local_error(WrapperErrorKind::ParamsMissing)
266                })?,
267            ))),
268            EccSchemeAlgorithm::EcMqv => Ok(EccScheme::EcMqv(HashScheme::new(
269                hashing_algorithm.ok_or_else(|| {
270                    error!("Hashing algorithm is required when creating ECC scheme of type EC MQV");
271                    Error::local_error(WrapperErrorKind::ParamsMissing)
272                })?,
273            ))),
274            EccSchemeAlgorithm::Null => {
275                if hashing_algorithm.is_none() {
276                    Ok(EccScheme::Null)
277                } else {
278                    error!("A hashing algorithm shall not be provided when creating ECC scheme of type Null");
279                    Err(Error::local_error(WrapperErrorKind::InconsistentParams))
280                }
281            }
282        }
283    }
284
285    pub fn algorithm(&self) -> EccSchemeAlgorithm {
286        match self {
287            EccScheme::EcDsa(_) => EccSchemeAlgorithm::EcDsa,
288            EccScheme::EcDh(_) => EccSchemeAlgorithm::EcDh,
289            EccScheme::EcDaa(_) => EccSchemeAlgorithm::EcDaa,
290            EccScheme::Sm2(_) => EccSchemeAlgorithm::Sm2,
291            EccScheme::EcSchnorr(_) => EccSchemeAlgorithm::EcSchnorr,
292            EccScheme::EcMqv(_) => EccSchemeAlgorithm::EcMqv,
293            EccScheme::Null => EccSchemeAlgorithm::Null,
294        }
295    }
296}
297
298impl From<EccScheme> for TPMT_ECC_SCHEME {
299    fn from(ecc_scheme: EccScheme) -> Self {
300        match ecc_scheme {
301            EccScheme::EcDsa(hash_scheme) => TPMT_ECC_SCHEME {
302                scheme: ecc_scheme.algorithm().into(),
303                details: TPMU_ASYM_SCHEME {
304                    ecdsa: hash_scheme.into(),
305                },
306            },
307            EccScheme::EcDh(hash_scheme) => TPMT_ECC_SCHEME {
308                scheme: ecc_scheme.algorithm().into(),
309                details: TPMU_ASYM_SCHEME {
310                    ecdh: hash_scheme.into(),
311                },
312            },
313            EccScheme::EcDaa(ec_daa_scheme) => TPMT_ECC_SCHEME {
314                scheme: ecc_scheme.algorithm().into(),
315                details: TPMU_ASYM_SCHEME {
316                    ecdaa: ec_daa_scheme.into(),
317                },
318            },
319
320            EccScheme::Sm2(hash_scheme) => TPMT_ECC_SCHEME {
321                scheme: ecc_scheme.algorithm().into(),
322                details: TPMU_ASYM_SCHEME {
323                    sm2: hash_scheme.into(),
324                },
325            },
326            EccScheme::EcSchnorr(hash_scheme) => TPMT_ECC_SCHEME {
327                scheme: ecc_scheme.algorithm().into(),
328                details: TPMU_ASYM_SCHEME {
329                    ecschnorr: hash_scheme.into(),
330                },
331            },
332            EccScheme::EcMqv(hash_scheme) => TPMT_ECC_SCHEME {
333                scheme: ecc_scheme.algorithm().into(),
334                details: TPMU_ASYM_SCHEME {
335                    ecmqv: hash_scheme.into(),
336                },
337            },
338            EccScheme::Null => TPMT_ECC_SCHEME {
339                scheme: ecc_scheme.algorithm().into(),
340                details: Default::default(),
341            },
342        }
343    }
344}
345
346impl TryFrom<TPMT_ECC_SCHEME> for EccScheme {
347    type Error = Error;
348
349    fn try_from(tpmt_ecc_scheme: TPMT_ECC_SCHEME) -> Result<Self> {
350        match EccSchemeAlgorithm::try_from(tpmt_ecc_scheme.scheme)? {
351            EccSchemeAlgorithm::EcDsa => Ok(EccScheme::EcDsa(
352                unsafe { tpmt_ecc_scheme.details.ecdsa }.try_into()?,
353            )),
354            EccSchemeAlgorithm::EcDh => Ok(EccScheme::EcDh(
355                unsafe { tpmt_ecc_scheme.details.ecdh }.try_into()?,
356            )),
357            EccSchemeAlgorithm::EcDaa => Ok(EccScheme::EcDaa(
358                unsafe { tpmt_ecc_scheme.details.ecdaa }.try_into()?,
359            )),
360            EccSchemeAlgorithm::Sm2 => Ok(EccScheme::Sm2(
361                unsafe { tpmt_ecc_scheme.details.sm2 }.try_into()?,
362            )),
363            EccSchemeAlgorithm::EcSchnorr => Ok(EccScheme::EcSchnorr(
364                unsafe { tpmt_ecc_scheme.details.ecschnorr }.try_into()?,
365            )),
366            EccSchemeAlgorithm::EcMqv => Ok(EccScheme::EcMqv(
367                unsafe { tpmt_ecc_scheme.details.ecmqv }.try_into()?,
368            )),
369            EccSchemeAlgorithm::Null => Ok(EccScheme::Null),
370        }
371    }
372}
373
374/// Enum representing the kdf scheme
375///
376/// # Details
377/// This corresponds to TPMT_KDF_SCHEME.
378#[derive(Clone, Copy, Debug, PartialEq, Eq)]
379pub enum KeyDerivationFunctionScheme {
380    Kdf1Sp800_56a(HashScheme),
381    Kdf2(HashScheme),
382    Kdf1Sp800_108(HashScheme),
383    Mgf1(HashScheme),
384    Null,
385}
386
387impl From<KeyDerivationFunctionScheme> for TPMT_KDF_SCHEME {
388    fn from(key_derivation_function_scheme: KeyDerivationFunctionScheme) -> Self {
389        match key_derivation_function_scheme {
390            KeyDerivationFunctionScheme::Kdf1Sp800_56a(hash_scheme) => TPMT_KDF_SCHEME {
391                scheme: KeyDerivationFunction::Kdf1Sp800_56a.into(),
392                details: TPMU_KDF_SCHEME {
393                    kdf1_sp800_56a: hash_scheme.into(),
394                },
395            },
396            KeyDerivationFunctionScheme::Kdf2(hash_scheme) => TPMT_KDF_SCHEME {
397                scheme: KeyDerivationFunction::Kdf2.into(),
398                details: TPMU_KDF_SCHEME {
399                    kdf2: hash_scheme.into(),
400                },
401            },
402            KeyDerivationFunctionScheme::Kdf1Sp800_108(hash_scheme) => TPMT_KDF_SCHEME {
403                scheme: KeyDerivationFunction::Kdf1Sp800_108.into(),
404                details: TPMU_KDF_SCHEME {
405                    kdf1_sp800_108: hash_scheme.into(),
406                },
407            },
408            KeyDerivationFunctionScheme::Mgf1(hash_scheme) => TPMT_KDF_SCHEME {
409                scheme: KeyDerivationFunction::Mgf1.into(),
410                details: TPMU_KDF_SCHEME {
411                    mgf1: hash_scheme.into(),
412                },
413            },
414            KeyDerivationFunctionScheme::Null => TPMT_KDF_SCHEME {
415                scheme: KeyDerivationFunction::Null.into(),
416                details: Default::default(),
417            },
418        }
419    }
420}
421
422impl TryFrom<TPMT_KDF_SCHEME> for KeyDerivationFunctionScheme {
423    type Error = Error;
424
425    fn try_from(tpmt_kdf_scheme: TPMT_KDF_SCHEME) -> Result<Self> {
426        match KeyDerivationFunction::try_from(tpmt_kdf_scheme.scheme)? {
427            KeyDerivationFunction::Kdf1Sp800_56a => Ok(KeyDerivationFunctionScheme::Kdf1Sp800_56a(
428                unsafe { tpmt_kdf_scheme.details.kdf1_sp800_56a }.try_into()?,
429            )),
430            KeyDerivationFunction::Kdf2 => Ok(KeyDerivationFunctionScheme::Kdf2(
431                unsafe { tpmt_kdf_scheme.details.kdf2 }.try_into()?,
432            )),
433            KeyDerivationFunction::Kdf1Sp800_108 => Ok(KeyDerivationFunctionScheme::Kdf1Sp800_108(
434                unsafe { tpmt_kdf_scheme.details.kdf1_sp800_108 }.try_into()?,
435            )),
436            KeyDerivationFunction::Mgf1 => Ok(KeyDerivationFunctionScheme::Mgf1(
437                unsafe { tpmt_kdf_scheme.details.mgf1 }.try_into()?,
438            )),
439            KeyDerivationFunction::Null => Ok(KeyDerivationFunctionScheme::Null),
440        }
441    }
442}
443
444/// Enum representing the rsa decryption scheme
445///
446/// # Details
447/// This corresponds to TPMT_RSA_DECRYPT.
448#[derive(Clone, Copy, Debug)]
449pub enum RsaDecryptionScheme {
450    RsaEs,
451    Oaep(HashScheme),
452    Null,
453}
454
455impl RsaDecryptionScheme {
456    /// Creates a new rsa decrypt scheme
457    pub fn create(
458        rsa_decrypt_algorithm: RsaDecryptAlgorithm,
459        hashing_algorithm: Option<HashingAlgorithm>,
460    ) -> Result<RsaDecryptionScheme> {
461        match rsa_decrypt_algorithm {
462            RsaDecryptAlgorithm::RsaEs => {
463                if hashing_algorithm.is_none() {
464                    Ok(RsaDecryptionScheme::RsaEs)
465                } else {
466                    error!("A hashing algorithm shall not be provided when creating RSA decryption scheme of type RSA ES");
467                    Err(Error::local_error(WrapperErrorKind::InconsistentParams))
468                }
469            },
470            RsaDecryptAlgorithm::Oaep => Ok(RsaDecryptionScheme::Oaep(HashScheme::new(
471                hashing_algorithm.ok_or_else(|| {
472                    error!("Hashing algorithm is required when creating RSA decrypt scheme of type OEAP");
473                    Error::local_error(WrapperErrorKind::ParamsMissing)
474                })?,
475            ))),
476            RsaDecryptAlgorithm::Null => {
477                if hashing_algorithm.is_none() {
478                    Ok(RsaDecryptionScheme::Null)
479                } else {
480                    error!("A hashing algorithm shall not be provided when creating RSA decryption scheme of type Null");
481                    Err(Error::local_error(WrapperErrorKind::InconsistentParams))
482                }
483            }
484        }
485    }
486
487    /// Returns the rsa decrypt scheme algorithm
488    pub fn algorithm(&self) -> RsaDecryptAlgorithm {
489        match self {
490            RsaDecryptionScheme::RsaEs => RsaDecryptAlgorithm::RsaEs,
491            RsaDecryptionScheme::Oaep(_) => RsaDecryptAlgorithm::Oaep,
492            RsaDecryptionScheme::Null => RsaDecryptAlgorithm::Null,
493        }
494    }
495}
496
497impl From<RsaDecryptionScheme> for TPMT_RSA_DECRYPT {
498    fn from(rsa_decryption_scheme: RsaDecryptionScheme) -> Self {
499        match rsa_decryption_scheme {
500            RsaDecryptionScheme::RsaEs => TPMT_RSA_DECRYPT {
501                scheme: rsa_decryption_scheme.algorithm().into(),
502                details: TPMU_ASYM_SCHEME {
503                    rsaes: Default::default(),
504                },
505            },
506            RsaDecryptionScheme::Oaep(hash_scheme) => TPMT_RSA_DECRYPT {
507                scheme: rsa_decryption_scheme.algorithm().into(),
508                details: TPMU_ASYM_SCHEME {
509                    oaep: hash_scheme.into(),
510                },
511            },
512            RsaDecryptionScheme::Null => TPMT_RSA_DECRYPT {
513                scheme: rsa_decryption_scheme.algorithm().into(),
514                details: Default::default(),
515            },
516        }
517    }
518}
519
520impl TryFrom<TPMT_RSA_DECRYPT> for RsaDecryptionScheme {
521    type Error = Error;
522
523    fn try_from(tpmt_rsa_decrypt: TPMT_RSA_DECRYPT) -> Result<Self> {
524        match RsaDecryptAlgorithm::try_from(tpmt_rsa_decrypt.scheme)? {
525            RsaDecryptAlgorithm::RsaEs => Ok(RsaDecryptionScheme::RsaEs),
526            RsaDecryptAlgorithm::Oaep => Ok(RsaDecryptionScheme::Oaep(
527                unsafe { tpmt_rsa_decrypt.details.oaep }.try_into()?,
528            )),
529            RsaDecryptAlgorithm::Null => Ok(RsaDecryptionScheme::Null),
530        }
531    }
532}
533
534impl TryFrom<RsaScheme> for RsaDecryptionScheme {
535    type Error = Error;
536
537    fn try_from(rsa_scheme: RsaScheme) -> Result<Self> {
538        match rsa_scheme {
539            RsaScheme::RsaEs => Ok(RsaDecryptionScheme::RsaEs),
540            RsaScheme::Oaep(hash_scheme) => Ok(RsaDecryptionScheme::Oaep(hash_scheme)),
541            RsaScheme::Null => Ok(RsaDecryptionScheme::Null),
542            _ => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
543        }
544    }
545}
546
547/// Full description of signature schemes.
548///
549/// # Details
550/// Corresponds to `TPMT_SIG_SCHEME`.
551#[derive(Clone, Copy, Debug, Eq, PartialEq)]
552pub enum SignatureScheme {
553    RsaSsa { hash_scheme: HashScheme },
554    RsaPss { hash_scheme: HashScheme },
555    EcDsa { hash_scheme: HashScheme },
556    Sm2 { hash_scheme: HashScheme },
557    EcSchnorr { hash_scheme: HashScheme },
558    EcDaa { ecdaa_scheme: EcDaaScheme },
559    Hmac { hmac_scheme: HmacScheme },
560    Null,
561}
562
563impl SignatureScheme {
564    /// Returns the digest( i.e. hashing algorithm) of a signing scheme.
565    ///
566    /// # Details
567    /// This is intended to provide the functionality of reading
568    /// from the ```anySig``` field in the TPMU_SIG_SCHEME union.
569    ///
570    /// # Errors
571    /// Returns an InvalidParam error if the trying to read from
572    /// SignatureScheme that is not a signing scheme.
573    pub fn signing_scheme(&self) -> Result<HashingAlgorithm> {
574        match self {
575            SignatureScheme::RsaSsa { hash_scheme }
576            | SignatureScheme::RsaPss { hash_scheme }
577            | SignatureScheme::EcDsa { hash_scheme }
578            | SignatureScheme::Sm2 { hash_scheme }
579            | SignatureScheme::EcSchnorr { hash_scheme } => Ok(hash_scheme.hashing_algorithm()),
580            SignatureScheme::EcDaa { ecdaa_scheme } => Ok(ecdaa_scheme.hashing_algorithm()),
581            _ => {
582                error!("Cannot access digest for a non signing scheme");
583                Err(Error::local_error(WrapperErrorKind::InvalidParam))
584            }
585        }
586    }
587
588    /// Sets digest( i.e. hashing algorithm) of a signing scheme.
589    ///
590    /// # Details
591    /// This is intended to provide the functionality of writing
592    /// to the ```anySig``` field in the TPMU_SIG_SCHEME union.
593    ///
594    /// # Errors
595    /// Returns an InvalidParam error if the trying to read from
596    /// SignatureScheme that is not a signing scheme.
597    pub fn set_signing_scheme(&mut self, hashing_algorithm: HashingAlgorithm) -> Result<()> {
598        match self {
599            SignatureScheme::RsaSsa { hash_scheme }
600            | SignatureScheme::RsaPss { hash_scheme }
601            | SignatureScheme::EcDsa { hash_scheme }
602            | SignatureScheme::Sm2 { hash_scheme }
603            | SignatureScheme::EcSchnorr { hash_scheme } => {
604                *hash_scheme = HashScheme::new(hashing_algorithm);
605                Ok(())
606            }
607            SignatureScheme::EcDaa { ecdaa_scheme } => {
608                *ecdaa_scheme = EcDaaScheme::new(hashing_algorithm, ecdaa_scheme.count());
609                Ok(())
610            }
611            _ => {
612                error!("Cannot access digest for a non signing scheme");
613                Err(Error::local_error(WrapperErrorKind::InvalidParam))
614            }
615        }
616    }
617}
618
619impl From<SignatureScheme> for TPMT_SIG_SCHEME {
620    fn from(native: SignatureScheme) -> TPMT_SIG_SCHEME {
621        match native {
622            SignatureScheme::EcDaa { ecdaa_scheme } => TPMT_SIG_SCHEME {
623                scheme: SignatureSchemeAlgorithm::EcDaa.into(),
624                details: TPMU_SIG_SCHEME {
625                    ecdaa: ecdaa_scheme.into(),
626                },
627            },
628            SignatureScheme::EcDsa { hash_scheme } => TPMT_SIG_SCHEME {
629                scheme: SignatureSchemeAlgorithm::EcDsa.into(),
630                details: TPMU_SIG_SCHEME {
631                    ecdsa: hash_scheme.into(),
632                },
633            },
634            SignatureScheme::EcSchnorr { hash_scheme } => TPMT_SIG_SCHEME {
635                scheme: SignatureSchemeAlgorithm::EcSchnorr.into(),
636                details: TPMU_SIG_SCHEME {
637                    ecschnorr: hash_scheme.into(),
638                },
639            },
640            SignatureScheme::Hmac { hmac_scheme } => TPMT_SIG_SCHEME {
641                scheme: SignatureSchemeAlgorithm::Hmac.into(),
642                details: TPMU_SIG_SCHEME {
643                    hmac: hmac_scheme.into(),
644                },
645            },
646            SignatureScheme::Null => TPMT_SIG_SCHEME {
647                scheme: SignatureSchemeAlgorithm::Null.into(),
648                details: Default::default(),
649            },
650            SignatureScheme::RsaPss { hash_scheme } => TPMT_SIG_SCHEME {
651                scheme: SignatureSchemeAlgorithm::RsaPss.into(),
652                details: TPMU_SIG_SCHEME {
653                    rsapss: hash_scheme.into(),
654                },
655            },
656            SignatureScheme::RsaSsa { hash_scheme } => TPMT_SIG_SCHEME {
657                scheme: SignatureSchemeAlgorithm::RsaSsa.into(),
658                details: TPMU_SIG_SCHEME {
659                    rsassa: hash_scheme.into(),
660                },
661            },
662            SignatureScheme::Sm2 { hash_scheme } => TPMT_SIG_SCHEME {
663                scheme: SignatureSchemeAlgorithm::Sm2.into(),
664                details: TPMU_SIG_SCHEME {
665                    sm2: hash_scheme.into(),
666                },
667            },
668        }
669    }
670}
671
672impl TryFrom<TPMT_SIG_SCHEME> for SignatureScheme {
673    type Error = Error;
674
675    fn try_from(tss: TPMT_SIG_SCHEME) -> Result<Self> {
676        match SignatureSchemeAlgorithm::try_from(tss.scheme)? {
677            SignatureSchemeAlgorithm::EcDaa => Ok(SignatureScheme::EcDaa {
678                ecdaa_scheme: unsafe { tss.details.ecdaa }.try_into()?,
679            }),
680            SignatureSchemeAlgorithm::EcDsa => Ok(SignatureScheme::EcDsa {
681                hash_scheme: unsafe { tss.details.ecdsa }.try_into()?,
682            }),
683            SignatureSchemeAlgorithm::EcSchnorr => Ok(SignatureScheme::EcSchnorr {
684                hash_scheme: unsafe { tss.details.ecschnorr }.try_into()?,
685            }),
686            SignatureSchemeAlgorithm::Hmac => Ok(SignatureScheme::Hmac {
687                hmac_scheme: unsafe { tss.details.hmac }.try_into()?,
688            }),
689            SignatureSchemeAlgorithm::Null => Ok(SignatureScheme::Null),
690            SignatureSchemeAlgorithm::RsaPss => Ok(SignatureScheme::RsaPss {
691                hash_scheme: unsafe { tss.details.rsapss }.try_into()?,
692            }),
693            SignatureSchemeAlgorithm::RsaSsa => Ok(SignatureScheme::RsaSsa {
694                hash_scheme: unsafe { tss.details.rsassa }.try_into()?,
695            }),
696            SignatureSchemeAlgorithm::Sm2 => Ok(SignatureScheme::Sm2 {
697                hash_scheme: unsafe { tss.details.sm2 }.try_into()?,
698            }),
699        }
700    }
701}