tss_esapi/attributes/
locality.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0

use crate::{tss2_esys::TPMA_LOCALITY, Error, Result, WrapperErrorKind};
use bitfield::bitfield;
use log::error;

bitfield! {
    /// Bitfield representing the locality attributes.
    #[derive(Copy, Clone, Eq, PartialEq)]
    pub struct LocalityAttributes(TPMA_LOCALITY);
    impl Debug;

    _, set_locality_zero: 0;
    pub locality_zero, _: 0;
    _, set_locality_one: 1;
    pub locality_one, _: 1;
    _, set_locality_two: 2;
    pub locality_two, _: 2;
    _, set_locality_three: 3;
    pub locality_three, _: 3;
    _, set_locality_four: 4;
    pub locality_four, _: 4;
    _, set_extended: 7, 5;
    extended, _: 7, 5;
}

impl LocalityAttributes {
    pub const LOCALITY_ZERO: LocalityAttributes = LocalityAttributes(1);
    pub const LOCALITY_ONE: LocalityAttributes = LocalityAttributes(2);
    pub const LOCALITY_TWO: LocalityAttributes = LocalityAttributes(4);
    pub const LOCALITY_THREE: LocalityAttributes = LocalityAttributes(8);
    pub const LOCALITY_FOUR: LocalityAttributes = LocalityAttributes(16);
    /// Returns true if the attributes are extended
    pub fn is_extended(&self) -> bool {
        self.extended() != 0u8
    }

    /// Returns the LocalityAttributes as a number.
    ///
    /// # Errors
    /// If the attributes are not extended en InvalidParams error
    /// is returned.
    pub fn as_extended(&self) -> Result<u8> {
        if self.is_extended() {
            Ok(self.0)
        } else {
            error!("Cannot retrieve LocalityAttributes as extended when the attributes are not indicated to be extended");
            Err(Error::local_error(WrapperErrorKind::InvalidParam))
        }
    }

    /// Returns the builder used to construct LocalAttributes.
    pub const fn builder() -> LocalityAttributesBuilder {
        LocalityAttributesBuilder::new()
    }
}

impl From<TPMA_LOCALITY> for LocalityAttributes {
    fn from(tpma_locality: TPMA_LOCALITY) -> Self {
        LocalityAttributes(tpma_locality)
    }
}

impl From<LocalityAttributes> for TPMA_LOCALITY {
    fn from(locality_attributes: LocalityAttributes) -> Self {
        locality_attributes.0
    }
}

#[derive(Debug, Clone)]
pub struct LocalityAttributesBuilder {
    localities: Vec<u8>,
}

impl LocalityAttributesBuilder {
    /// Creates a new builder.
    pub const fn new() -> Self {
        LocalityAttributesBuilder {
            localities: Vec::new(),
        }
    }
    /// Adds a locality to the builder
    pub fn with_locality(mut self, locality: u8) -> Self {
        self.localities.push(locality);
        self
    }

    /// Adds a slice of localities to the builder
    pub fn with_localities(mut self, localities: &[u8]) -> Self {
        self.localities.extend_from_slice(localities);
        self
    }

    /// Builds the attributes
    pub fn build(self) -> Result<LocalityAttributes> {
        let mut locality_attributes = LocalityAttributes(0);
        for locality in self.localities {
            if locality_attributes.is_extended() {
                error!("Locality attribute {new} and locality attribute {prev} cannot be combined because locality attribute {prev} is extended", new=locality, prev=locality_attributes.0);
                return Err(Error::local_error(WrapperErrorKind::InvalidParam));
            }
            match locality {
                0 => locality_attributes.set_locality_zero(true),
                1 => locality_attributes.set_locality_one(true),
                2 => locality_attributes.set_locality_two(true),
                3 => locality_attributes.set_locality_three(true),
                4 => locality_attributes.set_locality_four(true),
                5..=31 => {
                    error!(
                        "Locality attribute {new} is invalid and cannot be combined with other locality attributes",
                        new=locality
                    );
                    return Err(Error::local_error(WrapperErrorKind::InvalidParam));
                }
                32..=255 => {
                    if locality_attributes.0 != 0 {
                        error!("Locality attribute {new} is extended and cannot be combined with locality attribute(s) {old}", new=locality, old=locality_attributes.0);
                        return Err(Error::local_error(WrapperErrorKind::InvalidParam));
                    }
                    locality_attributes.0 = locality;
                }
            }
        }
        Ok(locality_attributes)
    }
}

impl Default for LocalityAttributesBuilder {
    fn default() -> Self {
        Self::new()
    }
}