|
| 1 | +//! SymmetricKeyPackage types |
| 2 | +
|
| 3 | +use alloc::{string::String, vec::Vec}; |
| 4 | +use der::ErrorKind; |
| 5 | +use der::asn1::Utf8StringRef; |
| 6 | +use der::{ |
| 7 | + DecodeValue, EncodeValue, Enumerated, FixedTag, Header, Length, Reader, Sequence, Tag, Writer, |
| 8 | + asn1::OctetString, |
| 9 | +}; |
| 10 | +use x509_cert::attr::Attribute; |
| 11 | + |
| 12 | +macro_rules! impl_str_enum { |
| 13 | + ( |
| 14 | + $(#[$attr:meta])* $vis: vis enum $name: ident { |
| 15 | + $( $(#[$attr_item: meta])* $item: ident => $value: expr,)* |
| 16 | + } |
| 17 | + )=> { |
| 18 | + $(#[$attr])* |
| 19 | + $vis enum $name { |
| 20 | + $( $(#[$attr_item])* $item, )* |
| 21 | + } |
| 22 | + |
| 23 | + impl AsRef<str> for $name { |
| 24 | + fn as_ref(&self) -> &str { |
| 25 | + match self { |
| 26 | + $( Self::$item => $value, )* |
| 27 | + } |
| 28 | + } |
| 29 | + } |
| 30 | + |
| 31 | + impl<'d> DecodeValue<'d> for $name { |
| 32 | + type Error = der::Error; |
| 33 | + |
| 34 | + fn decode_value<R: Reader<'d>>(reader: &mut R, header: Header) -> der::Result<Self> { |
| 35 | + let value = Utf8StringRef::decode_value(reader, header)?; |
| 36 | + |
| 37 | + match value.as_ref() { |
| 38 | + $( $value => Ok(Self::$item), )* |
| 39 | + _ => Err(der::Error::new( |
| 40 | + ErrorKind::Value { tag: Self::TAG }, |
| 41 | + reader.position(), |
| 42 | + )), |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + impl EncodeValue for $name { |
| 48 | + fn value_len(&self) -> der::Result<Length> { |
| 49 | + Utf8StringRef::new(self.as_ref())?.value_len() |
| 50 | + } |
| 51 | + |
| 52 | + fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> { |
| 53 | + Utf8StringRef::new(self.as_ref())?.encode_value(encoder) |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + impl FixedTag for $name { |
| 58 | + const TAG: Tag = String::TAG; |
| 59 | + } |
| 60 | + |
| 61 | + |
| 62 | + }; |
| 63 | +} |
| 64 | + |
| 65 | +/// The `SymmetricKeyPackage` type is defined in [RFC 6031 Section 2.0]. |
| 66 | +/// |
| 67 | +/// ```text |
| 68 | +/// SymmetricKeyPackage ::= SEQUENCE { |
| 69 | +/// version KeyPkgVersion DEFAULT v1, |
| 70 | +/// sKeyPkgAttrs [0] SEQUENCE SIZE (1..MAX) OF Attribute |
| 71 | +/// {{ SKeyPkgAttributes }} OPTIONAL, |
| 72 | +/// sKeys SymmetricKeys, |
| 73 | +/// ... } |
| 74 | +/// ``` |
| 75 | +/// |
| 76 | +/// [RFC 6031 Section 2.0]: https://datatracker.ietf.org/doc/html/rfc6031#section-2 |
| 77 | +#[derive(Sequence, PartialEq, Eq)] |
| 78 | +#[allow(missing_docs)] |
| 79 | +pub struct SymmetricKeyPackage { |
| 80 | + #[asn1(default = "Default::default")] |
| 81 | + pub version: KeyPkgVersion, |
| 82 | + #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")] |
| 83 | + pub s_key_pkg_attrs: Option<Vec<Attribute>>, |
| 84 | + pub s_keys: SymmetricKeys, |
| 85 | +} |
| 86 | + |
| 87 | +/// The `SymmetricKeys` type is defined in [RFC 6031 Section 2.0]. |
| 88 | +/// |
| 89 | +/// ```text |
| 90 | +/// SymmetricKeys ::= SEQUENCE SIZE (1..MAX) OF OneSymmetricKey |
| 91 | +/// ``` |
| 92 | +/// |
| 93 | +/// [RFC 6031 Section 2.0]: https://datatracker.ietf.org/doc/html/rfc6031#section-2 |
| 94 | +pub type SymmetricKeys = Vec<OneSymmetricKey>; |
| 95 | + |
| 96 | +/// The `OneSymmetricKey` type is defined in [RFC 6031 Section 2.0]. |
| 97 | +/// |
| 98 | +/// ```text |
| 99 | +/// OneSymmetricKey ::= SEQUENCE { |
| 100 | +/// sKeyAttrs SEQUENCE SIZE (1..MAX) OF Attribute |
| 101 | +/// {{ SKeyAttributes }} OPTIONAL, |
| 102 | +/// sKey OCTET STRING OPTIONAL } |
| 103 | +/// ( WITH COMPONENTS { ..., sKeyAttrs PRESENT } | |
| 104 | +/// WITH COMPONENTS { ..., sKey PRESENT } ) |
| 105 | +/// ``` |
| 106 | +/// |
| 107 | +/// [RFC 6031 Section 2.0]: https://datatracker.ietf.org/doc/html/rfc6031#section-2 |
| 108 | +#[derive(Sequence, PartialEq, Eq)] |
| 109 | +#[allow(missing_docs)] |
| 110 | +pub struct OneSymmetricKey { |
| 111 | + pub s_key_attrs: Vec<Attribute>, |
| 112 | + #[asn1(optional = "true")] |
| 113 | + pub s_key: Option<OctetString>, |
| 114 | +} |
| 115 | + |
| 116 | +/// The `KeyPkgVersion` type is defined in [RFC 6031 Section 2.0]. |
| 117 | +/// |
| 118 | +/// ```text |
| 119 | +/// KeyPkgVersion ::= INTEGER { v1(1) } ( v1, ... ) |
| 120 | +/// ``` |
| 121 | +/// [RFC 6031 Section 2.0]: https://datatracker.ietf.org/doc/html/rfc6031#section-2 |
| 122 | +#[derive(Default, Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Enumerated)] |
| 123 | +#[asn1(type = "INTEGER")] |
| 124 | +#[repr(u8)] |
| 125 | +#[allow(missing_docs)] |
| 126 | +pub enum KeyPkgVersion { |
| 127 | + #[default] |
| 128 | + V1 = 1, |
| 129 | +} |
| 130 | + |
| 131 | +// todo: determine if all the types below should live in another file such as attr.rs |
| 132 | + |
| 133 | +/// The `FriendlyName` type is defined in [RFC 6031 Section 3.2.6]. |
| 134 | +/// |
| 135 | +/// ```text |
| 136 | +/// FriendlyName ::= SEQUENCE { |
| 137 | +/// friendlyName UTF8String, |
| 138 | +/// friendlyNameLangTag UTF8String OPTIONAL } |
| 139 | +/// ``` |
| 140 | +/// |
| 141 | +/// [RFC 6031 Section 3.2.6]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.2.6 |
| 142 | +#[derive(Sequence, PartialEq, Eq)] |
| 143 | +#[allow(missing_docs)] |
| 144 | +pub struct FriendlyName { |
| 145 | + pub friendly_name: String, |
| 146 | + #[asn1(optional = "true")] |
| 147 | + pub friendly_name_lang_tag: Option<String>, |
| 148 | +} |
| 149 | + |
| 150 | +/// The `PSKCAlgorithmParameters` type is defined in [RFC 6031 Section 3.2.7]. |
| 151 | +/// |
| 152 | +/// ```text |
| 153 | +/// PSKCAlgorithmParameters ::= CHOICE { |
| 154 | +/// suite UTF8String, |
| 155 | +/// challengeFormat [0] ChallengeFormat, |
| 156 | +/// responseFormat [1] ResponseFormat, |
| 157 | +/// ... } |
| 158 | +/// ``` |
| 159 | +/// |
| 160 | +/// [RFC 6031 Section 3.2.7]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.2.7 |
| 161 | +#[derive(Sequence, PartialEq, Eq)] |
| 162 | +#[allow(missing_docs)] |
| 163 | +pub struct PSKCAlgorithmParameters { |
| 164 | + pub suite: String, |
| 165 | + pub challenge_format: ChallengeFormat, |
| 166 | + pub response_format: ResponseFormat, |
| 167 | +} |
| 168 | + |
| 169 | +/// The `ChallengeFormat` type is defined in [RFC 6031 Section 3.2.7]. |
| 170 | +/// |
| 171 | +/// ```text |
| 172 | +/// ChallengeFormat ::= SEQUENCE { |
| 173 | +/// encoding Encoding, |
| 174 | +/// checkDigit BOOLEAN DEFAULT FALSE, |
| 175 | +/// min INTEGER (0..MAX), |
| 176 | +/// max INTEGER (0..MAX), |
| 177 | +/// ... } |
| 178 | +/// ``` |
| 179 | +/// |
| 180 | +/// [RFC 6031 Section 3.2.7]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.2.7 |
| 181 | +#[derive(Sequence, PartialEq, Eq)] |
| 182 | +#[allow(missing_docs)] |
| 183 | +pub struct ChallengeFormat { |
| 184 | + pub encoding: Encoding, |
| 185 | + #[asn1(default = "Default::default")] |
| 186 | + pub check_digit: bool, |
| 187 | + pub min: der::asn1::Int, |
| 188 | + pub max: der::asn1::Int, |
| 189 | +} |
| 190 | + |
| 191 | +impl_str_enum!( |
| 192 | + /// The `Encoding` type is defined in [RFC 6031 Section 3.2.7]. |
| 193 | + /// |
| 194 | + /// ```text |
| 195 | + /// Encoding ::= UTF8STRING ("DECIMAL" | "HEXADECIMAL" | |
| 196 | + /// "ALPHANUMERIC" |"BASE64" |"BINARY") |
| 197 | + /// ``` |
| 198 | + /// |
| 199 | + /// [RFC 6031 Section 3.2.7]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.2.7 |
| 200 | + #[derive(Copy, Clone, PartialEq, Eq)] |
| 201 | + pub enum Encoding { |
| 202 | + /// "DECIMAL" |
| 203 | + Decimal => "DECIMAL", |
| 204 | + /// "HEXADECIMAL", |
| 205 | + Hexadecimal => "HEXADECIMAL", |
| 206 | + /// "ALPHANUMERIC", |
| 207 | + Alphanumeric => "ALPHANUMERIC", |
| 208 | + /// "BASE64", |
| 209 | + Base64 => "BASE64", |
| 210 | + /// "BINARY", |
| 211 | + Binary => "BINARY", |
| 212 | + } |
| 213 | +); |
| 214 | + |
| 215 | +/// The `ResponseFormat` type is defined in [RFC 6031 Section 3.2.7]. |
| 216 | +/// |
| 217 | +/// ```text |
| 218 | +/// ResponseFormat ::= SEQUENCE { |
| 219 | +/// encoding Encoding, |
| 220 | +/// length INTEGER (0..MAX), |
| 221 | +/// checkDigit BOOLEAN DEFAULT FALSE, |
| 222 | +/// ... } |
| 223 | +/// ``` |
| 224 | +/// |
| 225 | +/// [RFC 6031 Section 3.2.7]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.2.7 |
| 226 | +#[derive(Sequence, PartialEq, Eq)] |
| 227 | +#[allow(missing_docs)] |
| 228 | +pub struct ResponseFormat { |
| 229 | + pub encoding: Encoding, |
| 230 | + pub length: u32, |
| 231 | + #[asn1(default = "Default::default")] |
| 232 | + pub check_digit: bool, |
| 233 | +} |
| 234 | + |
| 235 | +/// The `ValueMac` type is defined in [RFC 6031 Section 3.2.12]. |
| 236 | +/// |
| 237 | +/// ```text |
| 238 | +/// ValueMac ::= SEQUENCE { |
| 239 | +/// macAlgorithm UTF8String, |
| 240 | +/// mac UTF8String } |
| 241 | +/// ``` |
| 242 | +/// |
| 243 | +/// [RFC 6031 Section 3.2.12]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.2.12 |
| 244 | +#[derive(Sequence, PartialEq, Eq)] |
| 245 | +#[allow(missing_docs)] |
| 246 | +pub struct ValueMac { |
| 247 | + pub mac_algorithm: String, |
| 248 | + pub mac: String, |
| 249 | +} |
| 250 | + |
| 251 | +/// The `PSKCKeyUsages` type is defined in [RFC 6031 Section 3.3.4]. |
| 252 | +/// |
| 253 | +/// ```text |
| 254 | +/// PSKCKeyUsages ::= SEQUENCE OF PSKCKeyUsage |
| 255 | +/// ``` |
| 256 | +/// |
| 257 | +/// [RFC 6031 Section 3.3.4]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.3.4 |
| 258 | +pub type PSKCKeyUsages = Vec<PSKCKeyUsage>; |
| 259 | + |
| 260 | +impl_str_enum!( |
| 261 | + /// The `PSKCKeyUsage` type is defined in [RFC 6031 Section 3.3.4]. |
| 262 | + /// |
| 263 | + /// ```text |
| 264 | + /// PSKCKeyUsage ::= UTF8String ("OTP" | "CR" | "Encrypt" | |
| 265 | + /// "Integrity" | "Verify" | "Unlock" | "Decrypt" | |
| 266 | + /// "KeyWrap" | "Unwrap" | "Derive" | "Generate") |
| 267 | + /// ``` |
| 268 | + /// |
| 269 | + /// [RFC 6031 Section 3.3.4]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.3.4 |
| 270 | + #[derive(Copy, Clone, PartialEq, Eq)] |
| 271 | + pub enum PSKCKeyUsage { |
| 272 | + /// "OTP" |
| 273 | + Otp => "Otp", |
| 274 | + /// "CR" |
| 275 | + Cr => "CR", |
| 276 | + /// "Encrypt" |
| 277 | + Encrypt => "Encrypt", |
| 278 | + /// "Integrity" |
| 279 | + Integrity => "Integrity", |
| 280 | + /// "Verify" |
| 281 | + Verify => "Verify", |
| 282 | + /// "Unlock" |
| 283 | + Unlock => "Unlock", |
| 284 | + /// "Decrypt" |
| 285 | + Decrypt => "Decrypt", |
| 286 | + /// "KeyWrap" |
| 287 | + KeyWrap => "KeyWrap", |
| 288 | + /// "Unwrap" |
| 289 | + Unwrap => "Unwrap", |
| 290 | + /// "Derive" |
| 291 | + Derive => "Derive", |
| 292 | + /// "Generate" |
| 293 | + Generate => "Generate", |
| 294 | + } |
| 295 | +); |
| 296 | + |
| 297 | +/// The `PINPolicy` type is defined in [RFC 6031 Section 3.3.5] |
| 298 | +/// |
| 299 | +/// ```text |
| 300 | +/// PINPolicy ::= SEQUENCE { |
| 301 | +/// pinKeyId [0] UTF8String OPTIONAL, |
| 302 | +/// pinUsageMode [1] PINUsageMode, |
| 303 | +/// maxFailedAttempts [2] INTEGER (0..MAX) OPTIONAL, |
| 304 | +/// minLength [3] INTEGER (0..MAX) OPTIONAL, |
| 305 | +/// maxLength [4] INTEGER (0..MAX) OPTIONAL, |
| 306 | +/// pinEncoding [5] Encoding OPTIONAL } |
| 307 | +/// ``` |
| 308 | +/// |
| 309 | +/// [RFC 6031 Section 3.3.5]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.3.5 |
| 310 | +#[derive(Sequence, PartialEq, Eq)] |
| 311 | +#[allow(missing_docs)] |
| 312 | +pub struct PINPolicy { |
| 313 | + #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")] |
| 314 | + pub pin_key_id: Option<String>, |
| 315 | + #[asn1(context_specific = "1", tag_mode = "IMPLICIT")] |
| 316 | + pub pin_usage_mode: PINUsageMode, |
| 317 | + #[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")] |
| 318 | + pub max_failed_attempts: Option<u32>, |
| 319 | + #[asn1(context_specific = "3", tag_mode = "IMPLICIT", optional = "true")] |
| 320 | + pub min_length: Option<u32>, |
| 321 | + #[asn1(context_specific = "4", tag_mode = "IMPLICIT", optional = "true")] |
| 322 | + pub max_length: Option<u32>, |
| 323 | + #[asn1(context_specific = "5", tag_mode = "IMPLICIT", optional = "true")] |
| 324 | + pub pin_encoding: Option<Encoding>, |
| 325 | +} |
| 326 | + |
| 327 | +impl_str_enum!( |
| 328 | + |
| 329 | + /// The `PINUsageMode` type is defined in [RFC 6031 Section 3.3.5] |
| 330 | + /// |
| 331 | + /// ```text |
| 332 | + /// PINUsageMode ::= UTF8String ("Local" | "Prepend" | "Append" | |
| 333 | + /// "Algorithmic") |
| 334 | + /// ``` |
| 335 | + /// |
| 336 | + /// [RFC 6031 Section 3.3.5]: https://datatracker.ietf.org/doc/html/rfc6031#section-3.3.5 |
| 337 | + #[derive(Copy, Clone, PartialEq, Eq)] |
| 338 | + pub enum PINUsageMode { |
| 339 | + /// "Local" |
| 340 | + Local => "Local", |
| 341 | + /// "Prepend" |
| 342 | + Prepend => "Prepend", |
| 343 | + /// "Append" |
| 344 | + Append => "Append", |
| 345 | + /// "Algorithmic" |
| 346 | + Algorithmic => "Algorithmic", |
| 347 | + } |
| 348 | +); |
0 commit comments