Skip to main content

signstar_yubihsm2/object/
key.rs

1//! YubiHSM2 key metadata.
2
3use std::{collections::HashSet, fmt::Display, hash::Hash};
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7#[cfg(feature = "serde")]
8use serde_repr::{Deserialize_repr, Serialize_repr};
9
10use crate::object::{Capabilities, Id};
11
12/// YubiHSM2 object domain.
13///
14/// Objects can belong to one or many domains on the YubiHSM2.
15/// See [Core Concepts - Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#domains) for more details.
16#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
17#[cfg_attr(feature = "serde", derive(Deserialize_repr, Serialize_repr))]
18#[repr(u8)]
19pub enum Domain {
20    /// First domain.
21    One = 1,
22    /// Second domain.
23    Two = 2,
24    /// Third domain.
25    Three = 3,
26    /// Fourth domain.
27    Four = 4,
28    /// Fifth domain.
29    Five = 5,
30    /// Sixth domain.
31    Six = 6,
32    /// Seventh domain.
33    Seven = 7,
34    /// Eighth domain.
35    Eight = 8,
36    /// Ninth domain.
37    Nine = 9,
38    /// Tenth domain.
39    Ten = 10,
40    /// Eleventh domain.
41    Eleven = 11,
42    /// Twelfth domain.
43    Twelve = 12,
44    /// Thirteenth domain.
45    Thirteen = 13,
46    /// Fourteenth domain.
47    Fourteen = 14,
48    /// Fifteenth domain.
49    Fifteen = 15,
50    /// Sixteenth domain.
51    Sixteen = 16,
52}
53
54impl Display for Domain {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        write!(
57            f,
58            "{}",
59            match self {
60                Self::One => "1",
61                Self::Two => "2",
62                Self::Three => "3",
63                Self::Four => "4",
64                Self::Five => "5",
65                Self::Six => "6",
66                Self::Seven => "7",
67                Self::Eight => "8",
68                Self::Nine => "9",
69                Self::Ten => "10",
70                Self::Eleven => "11",
71                Self::Twelve => "12",
72                Self::Thirteen => "13",
73                Self::Fourteen => "14",
74                Self::Fifteen => "15",
75                Self::Sixteen => "16",
76            }
77        )
78    }
79}
80
81impl From<Domain> for yubihsm::Domain {
82    fn from(value: Domain) -> Self {
83        match value {
84            Domain::One => Self::DOM1,
85            Domain::Two => Self::DOM2,
86            Domain::Three => Self::DOM3,
87            Domain::Four => Self::DOM4,
88            Domain::Five => Self::DOM5,
89            Domain::Six => Self::DOM6,
90            Domain::Seven => Self::DOM7,
91            Domain::Eight => Self::DOM8,
92            Domain::Nine => Self::DOM9,
93            Domain::Ten => Self::DOM10,
94            Domain::Eleven => Self::DOM11,
95            Domain::Twelve => Self::DOM12,
96            Domain::Thirteen => Self::DOM13,
97            Domain::Fourteen => Self::DOM14,
98            Domain::Fifteen => Self::DOM15,
99            Domain::Sixteen => Self::DOM16,
100        }
101    }
102}
103
104/// A set of domains of an object on a YubiHSM2.
105///
106/// Each object is assigned to at least one [`Domain`].
107#[derive(Clone, Debug, Eq, PartialEq)]
108#[cfg_attr(
109    feature = "serde",
110    derive(Serialize, Deserialize),
111    serde(try_from = "HashSet<Domain>")
112)]
113pub struct Domains(HashSet<Domain>);
114
115impl TryFrom<HashSet<Domain>> for Domains {
116    type Error = crate::object::Error;
117
118    fn try_from(domains: HashSet<Domain>) -> Result<Self, Self::Error> {
119        if domains.is_empty() {
120            return Err(Self::Error::EmptySetOfDomains);
121        }
122        Ok(Self(domains))
123    }
124}
125
126impl Domains {
127    /// Converts this object into raw big-endian bytes.
128    pub fn to_be_bytes(&self) -> [u8; 2] {
129        yubihsm::Domain::from(self).bits().to_be_bytes()
130    }
131
132    /// Returns set of domains containing all available domains.
133    pub fn all() -> Self {
134        yubihsm::Domain::all().bits().into()
135    }
136}
137
138impl From<&Domains> for yubihsm::Domain {
139    fn from(value: &Domains) -> Self {
140        value
141            .0
142            .iter()
143            .map(|cap| yubihsm::Domain::from(*cap))
144            .fold(yubihsm::Domain::empty(), |acc, c| acc | c)
145    }
146}
147
148impl From<Domain> for Domains {
149    fn from(value: Domain) -> Self {
150        let mut domains = HashSet::new();
151        domains.insert(value);
152        Self(domains)
153    }
154}
155
156impl From<u16> for Domains {
157    fn from(value: u16) -> Self {
158        let mut domains = HashSet::new();
159        let yubi_domain = yubihsm::Domain::from_bits_retain(value);
160        for (yubi_dom, dom) in [
161            (yubihsm::Domain::DOM1, Domain::One),
162            (yubihsm::Domain::DOM2, Domain::Two),
163            (yubihsm::Domain::DOM3, Domain::Three),
164            (yubihsm::Domain::DOM4, Domain::Four),
165            (yubihsm::Domain::DOM5, Domain::Five),
166            (yubihsm::Domain::DOM6, Domain::Six),
167            (yubihsm::Domain::DOM7, Domain::Seven),
168            (yubihsm::Domain::DOM8, Domain::Eight),
169            (yubihsm::Domain::DOM9, Domain::Nine),
170            (yubihsm::Domain::DOM10, Domain::Ten),
171            (yubihsm::Domain::DOM11, Domain::Eleven),
172            (yubihsm::Domain::DOM12, Domain::Twelve),
173            (yubihsm::Domain::DOM13, Domain::Thirteen),
174            (yubihsm::Domain::DOM14, Domain::Fourteen),
175            (yubihsm::Domain::DOM15, Domain::Fifteen),
176            (yubihsm::Domain::DOM16, Domain::Sixteen),
177        ] {
178            if yubi_domain.contains(yubi_dom) {
179                domains.insert(dom);
180            }
181        }
182
183        Domains(domains)
184    }
185}
186
187/// Metadata about a key stored on a YubiHSM2.
188///
189/// This struct stores common parameters of keys regardless of their usage may describe
190/// authentication, wrapping and signing keys.
191#[derive(Debug)]
192#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
193pub struct KeyInfo {
194    /// Inner identifier used to track the key on the YubiHSM2.
195    pub key_id: Id,
196
197    /// Key domain.
198    ///
199    /// Must be in range `1..16`.
200    /// See [Core Concepts - Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#domains).
201    pub domains: Domains,
202
203    /// Capabilities of this key.
204    pub caps: Capabilities,
205}