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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! Object attributes specifying which operations are allowed to be performed
// Apparently bitflags isn't clippy-safe
#![allow(unknown_lints, redundant_field_names, suspicious_arithmetic_impl)]
use std::fmt;
use serde::ser::{Serialize, Serializer};
use serde::de::{self, Deserialize, Deserializer, Visitor};
bitflags! {
/// Object attributes specifying which operations are allowed to be performed
///
/// <https://developers.yubico.com/YubiHSM2/Concepts/Capability.html>
pub struct Capabilities: u64 {
/// asymmetric_decrypt_ecdh: perform ECDH operation
const ASYMMETRIC_DECRYPT_ECDH = 0x800;
/// asymmetric_decrypt_oaep: perform RSA-OAEP decryption
const ASYMMETRIC_DECRYPT_OAEP = 0x400;
/// asymmetric_decrypt_pkcs: perform RSA-PKCS1v1.5 decryption
const ASYMMETRIC_DECRYPT_PKCS = 0x200;
/// asymmetric_gen: generate asymmetric objects
const ASYMMETRIC_GEN = 0x10;
/// asymmetric_sign_ecdsa: compute ECDSA digital signature
const ASYMMETRIC_SIGN_ECDSA = 0x80;
/// asymmetric_sign_eddsa: compute EdDSA (i.e. Ed25519) digital signature
const ASYMMETRIC_SIGN_EDDSA = 0x100;
/// asymmetric_sign_pkcs: compute RSA-PKCS1v1.5 digital signature
const ASYMMETRIC_SIGN_PKCS = 0x20;
/// asymmetric_sign_pss: compute RSA-PSS digital signature
const ASYMMETRIC_SIGN_PSS = 0x40;
/// attest: create attestation (i.e. X.509 certificate) about an asymmetric object
const ATTEST = 0x4_0000_0000;
/// audit: read the log store
const AUDIT = 0x100_0000;
/// delete_asymmetric: delete asymmetric key objects
const DELETE_ASYMMETRIC = 0x200_0000_0000;
/// delete_authkey: delete AuthKey objects
const DELETE_AUTHKEY = 0x100_0000_0000;
/// delete_hmac_key: delete HMACKey objects
const DELETE_HMACKEY = 0x800_0000_0000;
/// delete_opaque: delete opaque objects
const DELETE_OPAQUE = 0x80_0000_0000;
/// delete_otp_aead_key: delete OTPAEADKey objects
const DELETE_OTP_AEAD_KEY = 0x2000_0000_0000;
/// delete_template: delete template objects
const DELETE_TEMPLATE = 0x1000_0000_0000;
/// delete_wrap_key: delete WrapKey objects
const DELETE_WRAPKEY = 0x400_0000_0000;
/// export_under_wrap: mark an object as exportable under keywrap
const EXPORT_UNDER_WRAP = 0x1_0000;
/// export_wrapped: export objects under keywrap
const EXPORT_WRAPPED = 0x1000;
/// generate_otp_aead_key: generate OTPAEADKey objects
const GENERATE_OTP_AEAD_KEY = 0x10_0000_0000;
/// generate_wrapkey: generate wrapkey objects
const GENERATE_WRAPKEY = 0x8000;
/// get_opaque: read opaque objects
const GET_OPAQUE = 0x1;
/// get_option: read device-global options
const GET_OPTION = 0x4_0000;
/// get_randomness: extract random bytes
const GET_RANDOMNESS = 0x8_0000;
/// get_template: read template objects
const GET_TEMPLATE = 0x400_0000;
/// hmackey_generate: generate HMACKey objects
const HMACKEY_GENERATE = 0x20_0000;
/// hmac_data: compute HMAC for data
const HMAC_DATA = 0x40_0000;
/// hmac_verify: verify HMAC for data
const HMAC_VERIFY = 0x80_0000;
/// import_wrapped: import keywrapped objects
const IMPORT_WRAPPED = 0x2000;
/// otp_aead_create: create an OTP AEAD
const OTP_AEAD_CREATE = 0x4000_0000;
/// otp_aead_random: create an OTP AEAD from random data
const OTP_AEAD_RANDOM = 0x8000_0000;
/// otp_aead_rewrap_from: rewrap AEADs from one OTPAEADKey Object to another
const OTP_AEAD_REWRAP_FROM = 0x1_0000_0000;
/// otp_aead_rewrap_to: rewrap AEADs to one OTPAEADKey Object from another
const OTP_AEAD_REWRAP_TO = 0x2_0000_0000;
/// otp_decrypt: decrypt OTP
const OTP_DECRYPT = 0x2000_0000;
/// put_asymmetric: write asymmetric objects
const PUT_ASYMMETRIC = 0x8;
/// put_authkey: write AuthKey objects
const PUT_AUTHKEY = 0x4;
/// put_hmackey: write HMACKey objects
const PUT_HMACKEY = 0x10_0000;
/// put_opaque: Write Opaque Objects
const PUT_OPAQUE = 0x2;
/// put_option: write device-global options
const PUT_OPTION = 0x2_0000;
/// put_otp_aead_key: write OTPAEADKey objects
const PUT_OTP_AEAD_KEY = 0x8_0000_0000;
/// put_template: write template objects
const PUT_TEMPLATE = 0x800_0000;
/// put_wrapkey: write WrapKey objects
const PUT_WRAPKEY = 0x4000;
/// reset: factory reset the device
const RESET = 0x1000_0000;
/// ssh_certify: sign SSH certificates
const SSH_CERTIFY = 0x200_0000;
/// unwrap_data: unwrap user-provided data
const UNWRAP_DATA = 0x40_0000_0000;
/// wrap_data: wrap user-provided data
const WRAP_DATA = 0x20_0000_0000;
}
}
impl Default for Capabilities {
fn default() -> Self {
Capabilities::empty()
}
}
impl Serialize for Capabilities {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u64(self.bits())
}
}
impl<'de> Deserialize<'de> for Capabilities {
fn deserialize<D>(deserializer: D) -> Result<Capabilities, D::Error>
where
D: Deserializer<'de>,
{
struct CapabilitiesVisitor;
impl<'de> Visitor<'de> for CapabilitiesVisitor {
type Value = Capabilities;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("8-bytes containing capability bitflags")
}
fn visit_u64<E>(self, value: u64) -> Result<Capabilities, E>
where
E: de::Error,
{
Capabilities::from_bits(value)
.ok_or_else(|| E::custom("invalid capability bitflags"))
}
}
deserializer.deserialize_u64(CapabilitiesVisitor)
}
}