1use std::fmt::Write;
19
20use crate::asn1::Asn1Object;
21use crate::error::ErrorStack;
22use crate::nid::Nid;
23use crate::x509::{GeneralName, Stack, X509Extension, X509v3Context};
24use foreign_types::ForeignType;
25
26pub struct BasicConstraints {
28 critical: bool,
29 ca: bool,
30 pathlen: Option<u32>,
31}
32
33impl Default for BasicConstraints {
34 fn default() -> BasicConstraints {
35 BasicConstraints::new()
36 }
37}
38
39impl BasicConstraints {
40 #[must_use]
42 pub fn new() -> BasicConstraints {
43 BasicConstraints {
44 critical: false,
45 ca: false,
46 pathlen: None,
47 }
48 }
49
50 pub fn critical(&mut self) -> &mut BasicConstraints {
52 self.critical = true;
53 self
54 }
55
56 pub fn ca(&mut self) -> &mut BasicConstraints {
58 self.ca = true;
59 self
60 }
61
62 pub fn pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints {
65 self.pathlen = Some(pathlen);
66 self
67 }
68
69 pub fn build(&self) -> Result<X509Extension, ErrorStack> {
71 let mut value = String::new();
72 if self.critical {
73 value.push_str("critical,");
74 }
75 value.push_str("CA:");
76 if self.ca {
77 value.push_str("TRUE");
78 } else {
79 value.push_str("FALSE");
80 }
81 if let Some(pathlen) = self.pathlen {
82 write!(value, ",pathlen:{pathlen}").unwrap();
83 }
84 X509Extension::new_nid(None, None, Nid::BASIC_CONSTRAINTS, &value)
85 }
86}
87
88pub struct KeyUsage {
90 critical: bool,
91 digital_signature: bool,
92 non_repudiation: bool,
93 key_encipherment: bool,
94 data_encipherment: bool,
95 key_agreement: bool,
96 key_cert_sign: bool,
97 crl_sign: bool,
98 encipher_only: bool,
99 decipher_only: bool,
100}
101
102impl Default for KeyUsage {
103 fn default() -> KeyUsage {
104 KeyUsage::new()
105 }
106}
107
108impl KeyUsage {
109 #[must_use]
111 pub fn new() -> KeyUsage {
112 KeyUsage {
113 critical: false,
114 digital_signature: false,
115 non_repudiation: false,
116 key_encipherment: false,
117 data_encipherment: false,
118 key_agreement: false,
119 key_cert_sign: false,
120 crl_sign: false,
121 encipher_only: false,
122 decipher_only: false,
123 }
124 }
125
126 pub fn critical(&mut self) -> &mut KeyUsage {
128 self.critical = true;
129 self
130 }
131
132 pub fn digital_signature(&mut self) -> &mut KeyUsage {
134 self.digital_signature = true;
135 self
136 }
137
138 pub fn non_repudiation(&mut self) -> &mut KeyUsage {
140 self.non_repudiation = true;
141 self
142 }
143
144 pub fn key_encipherment(&mut self) -> &mut KeyUsage {
146 self.key_encipherment = true;
147 self
148 }
149
150 pub fn data_encipherment(&mut self) -> &mut KeyUsage {
152 self.data_encipherment = true;
153 self
154 }
155
156 pub fn key_agreement(&mut self) -> &mut KeyUsage {
158 self.key_agreement = true;
159 self
160 }
161
162 pub fn key_cert_sign(&mut self) -> &mut KeyUsage {
164 self.key_cert_sign = true;
165 self
166 }
167
168 pub fn crl_sign(&mut self) -> &mut KeyUsage {
170 self.crl_sign = true;
171 self
172 }
173
174 pub fn encipher_only(&mut self) -> &mut KeyUsage {
176 self.encipher_only = true;
177 self
178 }
179
180 pub fn decipher_only(&mut self) -> &mut KeyUsage {
182 self.decipher_only = true;
183 self
184 }
185
186 pub fn build(&self) -> Result<X509Extension, ErrorStack> {
188 let mut value = String::new();
189 let mut first = true;
190 append(&mut value, &mut first, self.critical, "critical");
191 append(
192 &mut value,
193 &mut first,
194 self.digital_signature,
195 "digitalSignature",
196 );
197 append(
198 &mut value,
199 &mut first,
200 self.non_repudiation,
201 "nonRepudiation",
202 );
203 append(
204 &mut value,
205 &mut first,
206 self.key_encipherment,
207 "keyEncipherment",
208 );
209 append(
210 &mut value,
211 &mut first,
212 self.data_encipherment,
213 "dataEncipherment",
214 );
215 append(&mut value, &mut first, self.key_agreement, "keyAgreement");
216 append(&mut value, &mut first, self.key_cert_sign, "keyCertSign");
217 append(&mut value, &mut first, self.crl_sign, "cRLSign");
218 append(&mut value, &mut first, self.encipher_only, "encipherOnly");
219 append(&mut value, &mut first, self.decipher_only, "decipherOnly");
220 X509Extension::new_nid(None, None, Nid::KEY_USAGE, &value)
221 }
222}
223
224pub struct ExtendedKeyUsage {
227 critical: bool,
228 items: Vec<String>,
229}
230
231impl Default for ExtendedKeyUsage {
232 fn default() -> ExtendedKeyUsage {
233 ExtendedKeyUsage::new()
234 }
235}
236
237impl ExtendedKeyUsage {
238 #[must_use]
240 pub fn new() -> ExtendedKeyUsage {
241 ExtendedKeyUsage {
242 critical: false,
243 items: vec![],
244 }
245 }
246
247 pub fn critical(&mut self) -> &mut ExtendedKeyUsage {
249 self.critical = true;
250 self
251 }
252
253 pub fn server_auth(&mut self) -> &mut ExtendedKeyUsage {
255 self.other("serverAuth")
256 }
257
258 pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage {
260 self.other("clientAuth")
261 }
262
263 pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage {
265 self.other("codeSigning")
266 }
267
268 pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage {
270 self.other("timeStamping")
271 }
272
273 pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage {
275 self.other("msCodeInd")
276 }
277
278 pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage {
280 self.other("msCodeCom")
281 }
282
283 pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage {
285 self.other("msCTLSign")
286 }
287
288 pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage {
290 self.other("msSGC")
291 }
292
293 pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage {
295 self.other("msEFS")
296 }
297
298 pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage {
300 self.other("nsSGC")
301 }
302
303 pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage {
305 self.items.push(other.to_string());
306 self
307 }
308
309 pub fn build(&self) -> Result<X509Extension, ErrorStack> {
311 let mut stack = Stack::new()?;
312 for item in &self.items {
313 stack.push(Asn1Object::from_str(item)?)?;
314 }
315 unsafe {
316 X509Extension::new_internal(Nid::EXT_KEY_USAGE, self.critical, stack.as_ptr().cast())
317 }
318 }
319}
320
321pub struct SubjectKeyIdentifier {
324 critical: bool,
325}
326
327impl Default for SubjectKeyIdentifier {
328 fn default() -> SubjectKeyIdentifier {
329 SubjectKeyIdentifier::new()
330 }
331}
332
333impl SubjectKeyIdentifier {
334 #[must_use]
336 pub fn new() -> SubjectKeyIdentifier {
337 SubjectKeyIdentifier { critical: false }
338 }
339
340 pub fn critical(&mut self) -> &mut SubjectKeyIdentifier {
342 self.critical = true;
343 self
344 }
345
346 pub fn build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack> {
348 let mut value = String::new();
349 let mut first = true;
350 append(&mut value, &mut first, self.critical, "critical");
351 append(&mut value, &mut first, true, "hash");
352 X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_KEY_IDENTIFIER, &value)
353 }
354}
355
356pub struct AuthorityKeyIdentifier {
359 critical: bool,
360 keyid: Option<bool>,
361 issuer: Option<bool>,
362}
363
364impl Default for AuthorityKeyIdentifier {
365 fn default() -> AuthorityKeyIdentifier {
366 AuthorityKeyIdentifier::new()
367 }
368}
369
370impl AuthorityKeyIdentifier {
371 #[must_use]
373 pub fn new() -> AuthorityKeyIdentifier {
374 AuthorityKeyIdentifier {
375 critical: false,
376 keyid: None,
377 issuer: None,
378 }
379 }
380
381 pub fn critical(&mut self) -> &mut AuthorityKeyIdentifier {
383 self.critical = true;
384 self
385 }
386
387 pub fn keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
389 self.keyid = Some(always);
390 self
391 }
392
393 pub fn issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
395 self.issuer = Some(always);
396 self
397 }
398
399 pub fn build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack> {
401 let mut value = String::new();
402 let mut first = true;
403 append(&mut value, &mut first, self.critical, "critical");
404 match self.keyid {
405 Some(true) => append(&mut value, &mut first, true, "keyid:always"),
406 Some(false) => append(&mut value, &mut first, true, "keyid"),
407 None => {}
408 }
409 match self.issuer {
410 Some(true) => append(&mut value, &mut first, true, "issuer:always"),
411 Some(false) => append(&mut value, &mut first, true, "issuer"),
412 None => {}
413 }
414 X509Extension::new_nid(None, Some(ctx), Nid::AUTHORITY_KEY_IDENTIFIER, &value)
415 }
416}
417
418enum RustGeneralName {
419 Dns(String),
420 Email(String),
421 Uri(String),
422 Ip(String),
423 Rid(String),
424}
425
426pub struct SubjectAlternativeName {
429 critical: bool,
430 items: Vec<RustGeneralName>,
431}
432
433impl Default for SubjectAlternativeName {
434 fn default() -> SubjectAlternativeName {
435 SubjectAlternativeName::new()
436 }
437}
438
439impl SubjectAlternativeName {
440 #[must_use]
442 pub fn new() -> SubjectAlternativeName {
443 SubjectAlternativeName {
444 critical: false,
445 items: vec![],
446 }
447 }
448
449 pub fn critical(&mut self) -> &mut SubjectAlternativeName {
451 self.critical = true;
452 self
453 }
454
455 pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName {
457 self.items.push(RustGeneralName::Email(email.to_string()));
458 self
459 }
460
461 pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName {
463 self.items.push(RustGeneralName::Uri(uri.to_string()));
464 self
465 }
466
467 pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName {
469 self.items.push(RustGeneralName::Dns(dns.to_string()));
470 self
471 }
472
473 pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName {
475 self.items.push(RustGeneralName::Rid(rid.to_string()));
476 self
477 }
478
479 pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName {
481 self.items.push(RustGeneralName::Ip(ip.to_string()));
482 self
483 }
484
485 #[deprecated = "dir_name is deprecated and always panics. Please file a bug if you have a use case for this."]
489 pub fn dir_name(&mut self, _dir_name: &str) -> &mut SubjectAlternativeName {
490 unimplemented!(
491 "This has not yet been adapted for the new internals. File a bug if you need this."
492 );
493 }
494
495 #[deprecated = "other_name is deprecated and always panics. Please file a bug if you have a use case for this."]
499 pub fn other_name(&mut self, _other_name: &str) -> &mut SubjectAlternativeName {
500 unimplemented!(
501 "This has not yet been adapted for the new internals. File a bug if you need this."
502 );
503 }
504
505 pub fn build(&self, _ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
507 let mut stack = Stack::new()?;
508 for item in &self.items {
509 let gn = match item {
510 RustGeneralName::Dns(s) => GeneralName::new_dns(s.as_bytes())?,
511 RustGeneralName::Email(s) => GeneralName::new_email(s.as_bytes())?,
512 RustGeneralName::Uri(s) => GeneralName::new_uri(s.as_bytes())?,
513 RustGeneralName::Ip(s) => {
514 GeneralName::new_ip(s.parse().map_err(|_| ErrorStack::get())?)?
515 }
516 RustGeneralName::Rid(s) => GeneralName::new_rid(Asn1Object::from_str(s)?)?,
517 };
518 stack.push(gn)?;
519 }
520
521 unsafe {
522 X509Extension::new_internal(Nid::SUBJECT_ALT_NAME, self.critical, stack.as_ptr().cast())
523 }
524 }
525}
526
527fn append(value: &mut String, first: &mut bool, should: bool, element: &str) {
528 if !should {
529 return;
530 }
531
532 if !*first {
533 value.push(',');
534 }
535 *first = false;
536 value.push_str(element);
537}