Skip to main content

tss_esapi/attributes/
locality.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{Error, Result, WrapperErrorKind, tss2_esys::TPMA_LOCALITY};
5use bitfield::bitfield;
6use log::error;
7
8bitfield! {
9    /// Bitfield representing the locality attributes.
10    #[derive(Copy, Clone, Eq, PartialEq)]
11    pub struct LocalityAttributes(TPMA_LOCALITY);
12    impl Debug;
13
14    _, set_locality_zero: 0;
15    pub locality_zero, _: 0;
16    _, set_locality_one: 1;
17    pub locality_one, _: 1;
18    _, set_locality_two: 2;
19    pub locality_two, _: 2;
20    _, set_locality_three: 3;
21    pub locality_three, _: 3;
22    _, set_locality_four: 4;
23    pub locality_four, _: 4;
24    _, set_extended: 7, 5;
25    extended, _: 7, 5;
26}
27
28impl LocalityAttributes {
29    pub const LOCALITY_ZERO: LocalityAttributes = LocalityAttributes(1);
30    pub const LOCALITY_ONE: LocalityAttributes = LocalityAttributes(2);
31    pub const LOCALITY_TWO: LocalityAttributes = LocalityAttributes(4);
32    pub const LOCALITY_THREE: LocalityAttributes = LocalityAttributes(8);
33    pub const LOCALITY_FOUR: LocalityAttributes = LocalityAttributes(16);
34    /// Returns true if the attributes are extended
35    pub fn is_extended(&self) -> bool {
36        self.extended() != 0u8
37    }
38
39    /// Returns the LocalityAttributes as a number.
40    ///
41    /// # Errors
42    /// If the attributes are not extended en InvalidParams error
43    /// is returned.
44    pub fn as_extended(&self) -> Result<u8> {
45        if self.is_extended() {
46            Ok(self.0)
47        } else {
48            error!(
49                "Cannot retrieve LocalityAttributes as extended when the attributes are not indicated to be extended"
50            );
51            Err(Error::local_error(WrapperErrorKind::InvalidParam))
52        }
53    }
54
55    /// Returns the builder used to construct LocalAttributes.
56    pub const fn builder() -> LocalityAttributesBuilder {
57        LocalityAttributesBuilder::new()
58    }
59}
60
61impl From<TPMA_LOCALITY> for LocalityAttributes {
62    fn from(tpma_locality: TPMA_LOCALITY) -> Self {
63        LocalityAttributes(tpma_locality)
64    }
65}
66
67impl From<LocalityAttributes> for TPMA_LOCALITY {
68    fn from(locality_attributes: LocalityAttributes) -> Self {
69        locality_attributes.0
70    }
71}
72
73#[derive(Debug, Clone)]
74pub struct LocalityAttributesBuilder {
75    localities: Vec<u8>,
76}
77
78impl LocalityAttributesBuilder {
79    /// Creates a new builder.
80    pub const fn new() -> Self {
81        LocalityAttributesBuilder {
82            localities: Vec::new(),
83        }
84    }
85    /// Adds a locality to the builder
86    pub fn with_locality(mut self, locality: u8) -> Self {
87        self.localities.push(locality);
88        self
89    }
90
91    /// Adds a slice of localities to the builder
92    pub fn with_localities(mut self, localities: &[u8]) -> Self {
93        self.localities.extend_from_slice(localities);
94        self
95    }
96
97    /// Builds the attributes
98    pub fn build(self) -> Result<LocalityAttributes> {
99        let mut locality_attributes = LocalityAttributes(0);
100        for locality in self.localities {
101            if locality_attributes.is_extended() {
102                error!(
103                    "Locality attribute {new} and locality attribute {prev} cannot be combined because locality attribute {prev} is extended",
104                    new = locality,
105                    prev = locality_attributes.0
106                );
107                return Err(Error::local_error(WrapperErrorKind::InvalidParam));
108            }
109            match locality {
110                0 => locality_attributes.set_locality_zero(true),
111                1 => locality_attributes.set_locality_one(true),
112                2 => locality_attributes.set_locality_two(true),
113                3 => locality_attributes.set_locality_three(true),
114                4 => locality_attributes.set_locality_four(true),
115                5..=31 => {
116                    error!(
117                        "Locality attribute {new} is invalid and cannot be combined with other locality attributes",
118                        new = locality
119                    );
120                    return Err(Error::local_error(WrapperErrorKind::InvalidParam));
121                }
122                32..=255 => {
123                    if locality_attributes.0 != 0 {
124                        error!(
125                            "Locality attribute {new} is extended and cannot be combined with locality attribute(s) {old}",
126                            new = locality,
127                            old = locality_attributes.0
128                        );
129                        return Err(Error::local_error(WrapperErrorKind::InvalidParam));
130                    }
131                    locality_attributes.0 = locality;
132                }
133            }
134        }
135        Ok(locality_attributes)
136    }
137}
138
139impl Default for LocalityAttributesBuilder {
140    fn default() -> Self {
141        Self::new()
142    }
143}