1use crate::blob;
4use crate::helpers::Pod;
5use crate::helpers::{Blob, BlobLayout};
6use std::convert::TryFrom;
7use winapi::shared::bcrypt::*;
8use winapi::shared::ntdef::ULONG;
9
10pub enum BlobType {
12 AesWrapKey,
13 DhPrivate,
14 DhPublic,
15 DsaPublic,
16 DsaPrivate,
17 EccPrivate,
18 EccPublic,
19 KeyData,
20 OpaqueKey,
21 PublicKey,
22 PrivateKey,
23 RsaFullPrivate,
24 RsaPrivate,
25 RsaPublic,
26 LegacyDhPrivate,
27 LegacyDhPublic,
28 LegacyDsaPrivate,
29 LegacyDsaPublic,
30 LegacyDsaV2Private,
31 LegacyRsaPrivate,
32 LegacyRsaPublic,
33}
34
35impl BlobType {
36 pub fn as_value(&self) -> &'static str {
37 match self {
38 BlobType::AesWrapKey => BCRYPT_AES_WRAP_KEY_BLOB,
39 BlobType::DhPrivate => BCRYPT_DH_PRIVATE_BLOB,
40 BlobType::DhPublic => BCRYPT_DH_PUBLIC_BLOB,
41 BlobType::DsaPublic => BCRYPT_DSA_PUBLIC_BLOB,
42 BlobType::DsaPrivate => BCRYPT_DSA_PRIVATE_BLOB,
43 BlobType::EccPrivate => BCRYPT_ECCPRIVATE_BLOB,
44 BlobType::EccPublic => BCRYPT_ECCPUBLIC_BLOB,
45 BlobType::KeyData => BCRYPT_KEY_DATA_BLOB,
46 BlobType::OpaqueKey => BCRYPT_OPAQUE_KEY_BLOB,
47 BlobType::PublicKey => BCRYPT_PUBLIC_KEY_BLOB,
48 BlobType::PrivateKey => BCRYPT_PRIVATE_KEY_BLOB,
49 BlobType::RsaFullPrivate => BCRYPT_RSAFULLPRIVATE_BLOB,
50 BlobType::RsaPrivate => BCRYPT_RSAPRIVATE_BLOB,
51 BlobType::RsaPublic => BCRYPT_RSAPUBLIC_BLOB,
52 BlobType::LegacyDhPrivate => LEGACY_DH_PRIVATE_BLOB,
53 BlobType::LegacyDhPublic => LEGACY_DH_PUBLIC_BLOB,
54 BlobType::LegacyDsaPrivate => LEGACY_DSA_PRIVATE_BLOB,
55 BlobType::LegacyDsaPublic => LEGACY_DSA_PUBLIC_BLOB,
56 BlobType::LegacyDsaV2Private => LEGACY_DSA_V2_PRIVATE_BLOB,
57 BlobType::LegacyRsaPrivate => LEGACY_RSAPRIVATE_BLOB,
58 BlobType::LegacyRsaPublic => LEGACY_RSAPUBLIC_BLOB,
59 }
60 }
61}
62
63impl<'a> TryFrom<&'a str> for BlobType {
64 type Error = &'a str;
65
66 fn try_from(val: &'a str) -> Result<BlobType, Self::Error> {
67 match val {
68 BCRYPT_AES_WRAP_KEY_BLOB => Ok(BlobType::AesWrapKey),
69 BCRYPT_DH_PRIVATE_BLOB => Ok(BlobType::DhPrivate),
70 BCRYPT_DH_PUBLIC_BLOB => Ok(BlobType::DhPublic),
71 BCRYPT_DSA_PUBLIC_BLOB => Ok(BlobType::DsaPublic),
72 BCRYPT_DSA_PRIVATE_BLOB => Ok(BlobType::DsaPrivate),
73 BCRYPT_ECCPRIVATE_BLOB => Ok(BlobType::EccPrivate),
74 BCRYPT_ECCPUBLIC_BLOB => Ok(BlobType::EccPublic),
75 BCRYPT_KEY_DATA_BLOB => Ok(BlobType::KeyData),
76 BCRYPT_OPAQUE_KEY_BLOB => Ok(BlobType::OpaqueKey),
77 BCRYPT_PUBLIC_KEY_BLOB => Ok(BlobType::PublicKey),
78 BCRYPT_PRIVATE_KEY_BLOB => Ok(BlobType::PrivateKey),
79 BCRYPT_RSAFULLPRIVATE_BLOB => Ok(BlobType::RsaFullPrivate),
80 BCRYPT_RSAPRIVATE_BLOB => Ok(BlobType::RsaPrivate),
81 BCRYPT_RSAPUBLIC_BLOB => Ok(BlobType::RsaPublic),
82 LEGACY_DH_PRIVATE_BLOB => Ok(BlobType::LegacyDhPrivate),
83 LEGACY_DH_PUBLIC_BLOB => Ok(BlobType::LegacyDhPublic),
84 LEGACY_DSA_PRIVATE_BLOB => Ok(BlobType::LegacyDsaPrivate),
85 LEGACY_DSA_PUBLIC_BLOB => Ok(BlobType::LegacyDsaPublic),
86 LEGACY_DSA_V2_PRIVATE_BLOB => Ok(BlobType::LegacyDsaV2Private),
87 LEGACY_RSAPRIVATE_BLOB => Ok(BlobType::LegacyRsaPrivate),
88 LEGACY_RSAPUBLIC_BLOB => Ok(BlobType::LegacyRsaPublic),
89 val => Err(val),
90 }
91 }
92}
93
94pub unsafe trait KeyBlob: Sized {
96 const VALID_MAGIC: &'static [ULONG];
100
101 fn is_magic_valid(magic: ULONG) -> bool {
102 let accepts_all = Self::VALID_MAGIC.is_empty();
103 accepts_all || Self::VALID_MAGIC.iter().any(|&x| x == magic)
104 }
105}
106
107impl<T> AsRef<Blob<ErasedKeyBlob>> for Blob<T>
108where
109 T: BlobLayout + KeyBlob,
110{
111 fn as_ref(&self) -> &Blob<ErasedKeyBlob> {
112 self.as_erased()
113 }
114}
115
116impl<T> Blob<T>
117where
118 T: BlobLayout + KeyBlob,
119{
120 pub fn magic(&self) -> ULONG {
121 self.as_erased().header().Magic
122 }
123
124 pub fn blob_type(&self) -> Option<BlobType> {
125 magic_to_blob_type(self.magic())
126 }
127
128 pub fn as_erased(&self) -> &Blob<ErasedKeyBlob> {
129 unsafe { self.ref_cast() }
133 }
134
135 pub fn try_into<U>(self: Box<Self>) -> Result<Box<Blob<U>>, Box<Self>>
138 where
139 U: BlobLayout + KeyBlob,
140 {
141 if !U::is_magic_valid(self.magic()) {
142 return Err(self);
143 }
144
145 Ok(Blob::<U>::from_boxed(self.into_bytes()))
146 }
147}
148
149macro_rules! key_blobs {
150 ($($name: ident, $blob: expr, magic: $([$($val: ident),*])?),*) => {
151 fn magic_to_blob_type(magic: ULONG) -> Option<BlobType> {
152 match magic {
153 $(
154 $($(| $val)* => Some($blob),)?
155 )*
156 _ => None
157 }
158 }
159
160 $(
161 unsafe impl KeyBlob for $name {
162 const VALID_MAGIC: &'static [ULONG] = &[$($($val),*)?];
163 }
164
165 )*
166 };
167}
168
169key_blobs! {
170 ErasedKeyBlob, BlobType::PublicKey, magic:,
171 DhKeyPublicBlob, BlobType::DhPublic, magic: [BCRYPT_DH_PUBLIC_MAGIC],
172 DhKeyPrivateBlob, BlobType::DhPrivate, magic: [BCRYPT_DH_PRIVATE_MAGIC],
173 DsaKeyPublicBlob, BlobType::DsaPublic, magic: [BCRYPT_DSA_PUBLIC_MAGIC],
174 DsaKeyPrivateBlob, BlobType::DsaPrivate, magic: [BCRYPT_DSA_PRIVATE_MAGIC],
175 DsaKeyPublicV2Blob, BlobType::DsaPublic, magic: [BCRYPT_DSA_PUBLIC_MAGIC_V2],
176 DsaKeyPrivateV2Blob, BlobType::DsaPrivate, magic: [BCRYPT_DSA_PRIVATE_MAGIC_V2],
177 EccKeyPublicBlob, BlobType::EccPublic, magic: [
178 BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC, BCRYPT_ECDH_PUBLIC_P256_MAGIC,
179 BCRYPT_ECDH_PUBLIC_P384_MAGIC, BCRYPT_ECDH_PUBLIC_P521_MAGIC,
180 BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC, BCRYPT_ECDSA_PUBLIC_P256_MAGIC,
181 BCRYPT_ECDSA_PUBLIC_P384_MAGIC, BCRYPT_ECDSA_PUBLIC_P521_MAGIC
182 ],
183 EccKeyPrivateBlob, BlobType::EccPrivate, magic: [
184 BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC, BCRYPT_ECDH_PRIVATE_P256_MAGIC,
185 BCRYPT_ECDH_PRIVATE_P384_MAGIC, BCRYPT_ECDH_PRIVATE_P521_MAGIC,
186 BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC, BCRYPT_ECDSA_PRIVATE_P256_MAGIC,
187 BCRYPT_ECDSA_PRIVATE_P384_MAGIC, BCRYPT_ECDSA_PRIVATE_P521_MAGIC
188 ],
189 RsaKeyPublicBlob, BlobType::RsaPublic, magic: [BCRYPT_RSAPUBLIC_MAGIC],
190 RsaKeyPrivateBlob, BlobType::RsaPrivate, magic: [BCRYPT_RSAPRIVATE_MAGIC],
191 RsaKeyFullPrivateBlob, BlobType::RsaFullPrivate, magic: [BCRYPT_RSAFULLPRIVATE_MAGIC]
192}
193
194blob! {
195 enum ErasedKeyBlob {},
197 header: BCRYPT_KEY_BLOB,
198 view: struct ref ErasedKeyPayload {
200 phantom[0],
201 }
202}
203
204unsafe impl Pod for BCRYPT_KEY_BLOB {}
205blob! {
206 enum RsaKeyPublicBlob {},
208 header: BCRYPT_RSAKEY_BLOB,
209 view: struct ref RsaKeyPublicPayload {
213 pub_exp[cbPublicExp],
214 modulus[cbModulus],
215 }
216}
217
218unsafe impl Pod for BCRYPT_RSAKEY_BLOB {}
219blob! {
220 enum RsaKeyPrivateBlob {},
222 header: BCRYPT_RSAKEY_BLOB,
223 view: struct ref RsaKeyPrivatePayload {
227 pub_exp[cbPublicExp],
228 modulus[cbModulus],
229 prime1[cbPrime1],
230 prime2[cbPrime2],
231 }
232}
233
234blob! {
235 enum RsaKeyFullPrivateBlob {},
237 header: BCRYPT_RSAKEY_BLOB,
238 view: struct ref RsaKeyFullPrivatePayload {
242 pub_exp[cbPublicExp],
243 modulus[cbModulus],
244 prime1[cbPrime1],
245 prime2[cbPrime2],
246 exponent1[cbPrime1],
247 exponent2[cbPrime2],
248 coeff[cbPrime1],
249 priv_exp[cbModulus],
250 }
251}
252
253unsafe impl Pod for BCRYPT_DH_KEY_BLOB {}
254blob! {
255 enum DhKeyPublicBlob {},
257 header: BCRYPT_DH_KEY_BLOB,
258 view: struct ref DhKeyPublicPayload {
262 modulus[cbKey],
263 generator[cbKey],
264 public[cbKey],
265 }
266}
267
268blob! {
269 enum DhKeyPrivateBlob {},
271 header: BCRYPT_DH_KEY_BLOB,
272 view: struct ref DhKeyPrivatePayload {
276 modulus[cbKey],
277 generator[cbKey],
278 public[cbKey],
279 priv_exp[cbKey],
280 }
281}
282
283unsafe impl Pod for BCRYPT_DSA_KEY_BLOB {}
284blob! {
285 enum DsaKeyPublicBlob {},
287 header: BCRYPT_DSA_KEY_BLOB,
288 view: struct ref DsaKeyPublicPayload {
292 modulus[cbKey],
293 generator[cbKey],
294 public[cbKey],
295 }
296}
297
298blob! {
299 enum DsaKeyPrivateBlob {},
301 header: BCRYPT_DSA_KEY_BLOB,
302 view: struct ref DsaKeyPrivatePayload {
306 modulus[cbKey],
307 generator[cbKey],
308 public[cbKey],
309 priv_exp[20],
310 }
311}
312
313unsafe impl Pod for BCRYPT_DSA_KEY_BLOB_V2 {}
314blob! {
315 enum DsaKeyPublicV2Blob {},
319 header: BCRYPT_DSA_KEY_BLOB_V2,
320 view: struct ref DsaKeyPublicV2Payload {
327 seed[cbSeedLength],
331 group[cbGroupSize],
332 modulus[cbKey],
333 generator[cbKey],
334 public[cbKey],
335 }
336}
337
338blob! {
339 enum DsaKeyPrivateV2Blob {},
343 header: BCRYPT_DSA_KEY_BLOB_V2,
344 view: struct ref DsaKeyPrivateV2Payload {
351 seed[cbSeedLength],
355 group[cbGroupSize],
356 modulus[cbKey],
357 generator[cbKey],
358 public[cbKey],
359 priv_exp[cbGroupSize],
360 }
361}
362
363unsafe impl Pod for BCRYPT_ECCKEY_BLOB {}
364blob! {
365 enum EccKeyPublicBlob {},
367 header: BCRYPT_ECCKEY_BLOB,
368 view: struct ref EccKeyPublicPayload {
372 x[cbKey],
373 y[cbKey],
374 }
375}
376
377blob! {
378 enum EccKeyPrivateBlob {},
380 header: BCRYPT_ECCKEY_BLOB,
381 view: struct ref EccKeyPrivatePayload {
385 x[cbKey],
386 y[cbKey],
387 d[cbKey],
388 }
389}