tss_esapi/abstraction/
cipher.rs

1// Copyright 2019 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    constants::AlgorithmIdentifier,
5    interface_types::{
6        algorithm::{HashingAlgorithm, SymmetricAlgorithm, SymmetricMode, SymmetricObject},
7        key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits},
8    },
9    structures::{SymmetricCipherParameters, SymmetricDefinition, SymmetricDefinitionObject},
10    Error, Result, WrapperErrorKind,
11};
12use std::convert::{TryFrom, TryInto};
13/// Block cipher identifiers
14///
15/// Structure useful for handling an abstract representation of ciphers. Ciphers are
16/// defined foremost through their symmetric algorithm and, depending on the type of that
17/// algorithm, on a set of other values.
18#[derive(Copy, Clone, Debug)]
19pub struct Cipher {
20    algorithm: SymmetricAlgorithm,
21    mode: Option<SymmetricMode>,
22    key_bits: Option<u16>,
23    hash: Option<HashingAlgorithm>,
24}
25
26impl Cipher {
27    /// Constructor for AES cipher identifier
28    ///
29    /// `key_bits` must be one of 128, 192 or 256.
30    pub fn aes(mode: SymmetricMode, key_bits: u16) -> Result<Self> {
31        match key_bits {
32            128 | 192 | 256 => (),
33            _ => return Err(Error::local_error(WrapperErrorKind::InvalidParam)),
34        }
35
36        Ok(Cipher {
37            algorithm: SymmetricAlgorithm::Aes,
38            mode: Some(mode),
39            key_bits: Some(key_bits),
40            hash: None,
41        })
42    }
43
44    /// Constructor for Camellia cipher identifier
45    ///
46    /// `key_bits` must be one of 128, 192 or 256.
47    pub fn camellia(mode: SymmetricMode, key_bits: u16) -> Result<Self> {
48        match key_bits {
49            128 | 192 | 256 => (),
50            _ => return Err(Error::local_error(WrapperErrorKind::InvalidParam)),
51        }
52
53        Ok(Cipher {
54            algorithm: SymmetricAlgorithm::Camellia,
55            mode: Some(mode),
56            key_bits: Some(key_bits),
57            hash: None,
58        })
59    }
60
61    /// Constructor for Triple DES cipher identifier
62    ///
63    /// `key_bits` must be one of 56, 112 or 168.
64    pub fn tdes(mode: SymmetricMode, key_bits: u16) -> Result<Self> {
65        match key_bits {
66            56 | 112 | 168 => (),
67            _ => return Err(Error::local_error(WrapperErrorKind::InvalidParam)),
68        }
69
70        Ok(Cipher {
71            algorithm: SymmetricAlgorithm::Tdes,
72            mode: Some(mode),
73            key_bits: Some(key_bits),
74            hash: None,
75        })
76    }
77
78    /// Constructor for SM4 cipher identifier
79    pub fn sm4(mode: SymmetricMode) -> Self {
80        Cipher {
81            algorithm: SymmetricAlgorithm::Sm4,
82            mode: Some(mode),
83            key_bits: Some(128),
84            hash: None,
85        }
86    }
87
88    /// Constructor for XOR "cipher" identifier
89    pub fn xor(hash: HashingAlgorithm) -> Self {
90        Cipher {
91            algorithm: SymmetricAlgorithm::Xor,
92            mode: None,
93            key_bits: None,
94            hash: Some(hash),
95        }
96    }
97
98    /// Get general object type for symmetric ciphers.
99    pub fn object_type() -> AlgorithmIdentifier {
100        AlgorithmIdentifier::SymCipher
101    }
102
103    /// Get the cipher key length.
104    pub fn key_bits(self) -> Option<u16> {
105        self.key_bits
106    }
107
108    /// Get the cipher mode.
109    pub fn mode(self) -> Option<SymmetricMode> {
110        self.mode
111    }
112
113    /// Get the hash algorithm used with an XOR cipher
114    pub fn hash(self) -> Option<HashingAlgorithm> {
115        self.hash
116    }
117
118    /// Get the symmetrical algorithm for the cipher.
119    pub fn algorithm(&self) -> SymmetricAlgorithm {
120        self.algorithm
121    }
122
123    /// Constructor for 128 bit AES in CFB mode.
124    pub fn aes_128_cfb() -> Self {
125        Cipher {
126            algorithm: SymmetricAlgorithm::Aes,
127            mode: Some(SymmetricMode::Cfb),
128            key_bits: Some(128),
129            hash: None,
130        }
131    }
132
133    /// Constructor for 256 bit AES in CFB mode.
134    pub fn aes_256_cfb() -> Self {
135        Cipher {
136            algorithm: SymmetricAlgorithm::Aes,
137            mode: Some(SymmetricMode::Cfb),
138            key_bits: Some(256),
139            hash: None,
140        }
141    }
142}
143
144impl TryFrom<Cipher> for SymmetricDefinition {
145    type Error = Error;
146    fn try_from(cipher: Cipher) -> Result<Self> {
147        match cipher.algorithm {
148            SymmetricAlgorithm::Aes => Ok(SymmetricDefinition::Aes {
149                key_bits: cipher
150                    .key_bits
151                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
152                    .and_then(AesKeyBits::try_from)?,
153                mode: cipher
154                    .mode
155                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?,
156            }),
157            SymmetricAlgorithm::Sm4 => Ok(SymmetricDefinition::Sm4 {
158                key_bits: cipher
159                    .key_bits
160                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
161                    .and_then(Sm4KeyBits::try_from)?,
162                mode: cipher
163                    .mode
164                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?,
165            }),
166            SymmetricAlgorithm::Camellia => Ok(SymmetricDefinition::Camellia {
167                key_bits: cipher
168                    .key_bits
169                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
170                    .and_then(CamelliaKeyBits::try_from)?,
171                mode: cipher
172                    .mode
173                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?,
174            }),
175            SymmetricAlgorithm::Xor => Ok(SymmetricDefinition::Xor {
176                hashing_algorithm: cipher
177                    .hash
178                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
179                    .and_then(|ha| {
180                        if ha != HashingAlgorithm::Null {
181                            Ok(ha)
182                        } else {
183                            Err(Error::local_error(WrapperErrorKind::InvalidParam))
184                        }
185                    })?,
186            }),
187            SymmetricAlgorithm::Null => Ok(SymmetricDefinition::Null),
188            SymmetricAlgorithm::Tdes => {
189                // TODO: Investigate
190                Err(Error::local_error(WrapperErrorKind::UnsupportedParam))
191            }
192        }
193    }
194}
195
196impl TryFrom<Cipher> for SymmetricDefinitionObject {
197    type Error = Error;
198    fn try_from(cipher: Cipher) -> Result<Self> {
199        match SymmetricObject::try_from(AlgorithmIdentifier::from(cipher.algorithm))? {
200            SymmetricObject::Aes => Ok(SymmetricDefinitionObject::Aes {
201                key_bits: cipher
202                    .key_bits
203                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
204                    .and_then(AesKeyBits::try_from)?,
205                mode: cipher
206                    .mode
207                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?,
208            }),
209            SymmetricObject::Sm4 => Ok(SymmetricDefinitionObject::Sm4 {
210                key_bits: cipher
211                    .key_bits
212                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
213                    .and_then(Sm4KeyBits::try_from)?,
214                mode: cipher
215                    .mode
216                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?,
217            }),
218            SymmetricObject::Camellia => Ok(SymmetricDefinitionObject::Camellia {
219                key_bits: cipher
220                    .key_bits
221                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))
222                    .and_then(CamelliaKeyBits::try_from)?,
223                mode: cipher
224                    .mode
225                    .ok_or_else(|| Error::local_error(WrapperErrorKind::ParamsMissing))?,
226            }),
227            SymmetricObject::Null => Ok(SymmetricDefinitionObject::Null),
228            SymmetricObject::Tdes => {
229                // TODO investigate
230                Err(Error::local_error(WrapperErrorKind::UnsupportedParam))
231            }
232        }
233    }
234}
235
236impl TryFrom<Cipher> for SymmetricCipherParameters {
237    type Error = Error;
238    fn try_from(cipher: Cipher) -> Result<Self> {
239        Ok(SymmetricCipherParameters::new(cipher.try_into()?))
240    }
241}