cert_helper/certificate/
builder.rs1use super::key::KeyType;
2use super::usage::Usage;
3use openssl::hash::MessageDigest;
4use openssl::pkey::{PKey, Private};
5use std::collections::HashSet;
6
7macro_rules! vec_str_to_hs {
8 ($vec:expr) => {
9 $vec.iter()
10 .map(|s| s.to_string())
11 .collect::<HashSet<String>>()
12 };
13}
14
15#[derive(Debug, Clone)]
17pub enum HashAlg {
18 SHA1,
20 SHA256,
22 SHA384,
24 SHA512,
26}
27pub trait BuilderCommon {
29 fn set_common_name(&mut self, name: &str);
30 fn set_signer(&mut self, signer: &str);
31 fn set_country_name(&mut self, name: &str);
32 fn set_state_province(&mut self, name: &str);
33 fn set_organization(&mut self, name: &str);
34 fn set_organization_unit(&mut self, name: &str);
35 fn set_alternative_names(&mut self, alternative_names: Vec<&str>);
36 fn set_locality_time(&mut self, locality_time: &str);
37 fn set_key_type(&mut self, key_type: KeyType);
38 fn set_signature_alg(&mut self, signature_alg: HashAlg);
39 fn set_key_usage(&mut self, key_usage: HashSet<Usage>);
40 fn set_private_key(&mut self, pkey: PKey<Private>);
41}
42
43#[derive(Debug)]
45pub struct BuilderFields {
46 pub(crate) common_name: String,
47 pub(crate) signer: Option<String>, pub(crate) alternative_names: HashSet<String>,
49 pub(crate) organization_unit: String,
50 pub(crate) country_name: String,
51 pub(crate) state_province: String,
52 pub(crate) organization: String,
53 pub(crate) locality_time: String,
54 pub(crate) key_type: Option<KeyType>,
55 pub(crate) existing_key: Option<PKey<Private>>,
56 pub(crate) signature_alg: Option<HashAlg>,
57 pub(crate) usage: Option<HashSet<Usage>>,
58}
59impl BuilderCommon for BuilderFields {
60 fn set_common_name(&mut self, common_name: &str) {
63 self.common_name = common_name.into();
64 }
65 fn set_alternative_names(&mut self, alternative_names: Vec<&str>) {
68 self.alternative_names
69 .extend(vec_str_to_hs!(alternative_names));
70 }
71 fn set_signer(&mut self, signer: &str) {
73 self.signer = Some(signer.into());
74 }
75 fn set_country_name(&mut self, country_name: &str) {
77 self.country_name = country_name.into();
78 }
79 fn set_state_province(&mut self, state_province: &str) {
81 self.state_province = state_province.into();
82 }
83 fn set_organization(&mut self, organization: &str) {
85 self.organization = organization.into();
86 }
87 fn set_organization_unit(&mut self, organization_unit: &str) {
89 self.organization_unit = organization_unit.into();
90 }
91 fn set_locality_time(&mut self, locality_time: &str) {
93 self.locality_time = locality_time.into();
94 }
95 fn set_key_type(&mut self, key_type: KeyType) {
97 self.key_type = Some(key_type);
98 }
99 fn set_signature_alg(&mut self, signature_alg: HashAlg) {
101 self.signature_alg = Some(signature_alg);
102 }
103 fn set_private_key(&mut self, pkey: PKey<Private>) {
105 self.existing_key = Some(pkey);
106 }
107 fn set_key_usage(&mut self, key_usage: HashSet<Usage>) {
109 match &mut self.usage {
110 Some(existing_usage) => {
111 existing_usage.extend(key_usage);
112 }
113 None => {
114 self.usage = Some(key_usage);
115 }
116 };
117 }
118}
119impl Default for BuilderFields {
120 fn default() -> Self {
122 Self {
123 common_name: Default::default(),
124 signer: Default::default(),
125 alternative_names: Default::default(),
126 country_name: Default::default(),
127 state_province: Default::default(),
128 organization: Default::default(),
129 organization_unit: Default::default(),
130 locality_time: Default::default(),
131 key_type: Default::default(),
132 signature_alg: Default::default(),
133 usage: Default::default(),
134 existing_key: Default::default(),
135 }
136 }
137}
138pub trait UseesBuilderFields: Sized {
140 fn fields_mut(&mut self) -> &mut BuilderFields;
142
143 fn common_name(mut self, common_name: &str) -> Self {
153 self.fields_mut().set_common_name(common_name);
154 self
155 }
156 fn signer(mut self, signer: &str) -> Self {
158 self.fields_mut().set_signer(signer);
159 self
160 }
161 fn alternative_names(mut self, alternative_names: Vec<&str>) -> Self {
170 self.fields_mut().set_alternative_names(alternative_names);
171 self
172 }
173 fn country_name(mut self, country_name: &str) -> Self {
175 self.fields_mut().set_country_name(country_name);
176 self
177 }
178 fn state_province(mut self, state_province: &str) -> Self {
180 self.fields_mut().set_state_province(state_province);
181 self
182 }
183 fn organization(mut self, organization: &str) -> Self {
185 self.fields_mut().set_organization(organization);
186 self
187 }
188 fn locality_time(mut self, locality_time: &str) -> Self {
190 self.fields_mut().set_locality_time(locality_time);
191 self
192 }
193 fn key_type(mut self, key_type: KeyType) -> Self {
195 self.fields_mut().set_key_type(key_type);
196 self
197 }
198 fn private_key(mut self, pkey: PKey<Private>) -> Self {
213 self.fields_mut().set_private_key(pkey);
214 self
215 }
216 fn signature_alg(mut self, signature_alg: HashAlg) -> Self {
218 self.fields_mut().set_signature_alg(signature_alg);
219 self
220 }
221
222 fn key_usage(mut self, key_usage: HashSet<Usage>) -> Self {
226 self.fields_mut().set_key_usage(key_usage);
227 self
228 }
229}
230
231pub(crate) fn select_hash(hash_type: &Option<HashAlg>) -> MessageDigest {
232 match hash_type {
233 Some(HashAlg::SHA1) => MessageDigest::sha1(),
234 Some(HashAlg::SHA384) => MessageDigest::sha384(),
235 Some(HashAlg::SHA512) => MessageDigest::sha512(),
236 _ => MessageDigest::sha256(),
237 }
238}