1 //! Add extensions to an `X509` certificate or certificate request.
2 //!
3 //! The extensions defined for X.509 v3 certificates provide methods for
4 //! associating additional attributes with users or public keys and for
5 //! managing relationships between CAs. The extensions created using this
6 //! module can be used with `X509v3Context` objects.
7 //!
8 //! # Example
9 //!
10 //! ```rust
11 //! extern crate openssl;
12 //!
13 //! use openssl::x509::extension::BasicConstraints;
14 //! use openssl::x509::X509Extension;
15 //!
16 //! fn main() {
17 //! let mut bc = BasicConstraints::new();
18 //! let bc = bc.critical().ca().pathlen(1);
19 //!
20 //! let extension: X509Extension = bc.build().unwrap();
21 //! }
22 //! ```
23 use std::fmt::Write;
24
25 use error::ErrorStack;
26 use nid::Nid;
27 use x509::{X509Extension, X509v3Context};
28
29 /// An extension which indicates whether a certificate is a CA certificate.
30 pub struct BasicConstraints {
31 critical: bool,
32 ca: bool,
33 pathlen: Option<u32>,
34 }
35
36 impl Default for BasicConstraints {
default() -> BasicConstraints37 fn default() -> BasicConstraints {
38 BasicConstraints::new()
39 }
40 }
41
42 impl BasicConstraints {
43 /// Construct a new `BasicConstraints` extension.
new() -> BasicConstraints44 pub fn new() -> BasicConstraints {
45 BasicConstraints {
46 critical: false,
47 ca: false,
48 pathlen: None,
49 }
50 }
51
52 /// Sets the `critical` flag to `true`. The extension will be critical.
critical(&mut self) -> &mut BasicConstraints53 pub fn critical(&mut self) -> &mut BasicConstraints {
54 self.critical = true;
55 self
56 }
57
58 /// Sets the `ca` flag to `true`.
ca(&mut self) -> &mut BasicConstraints59 pub fn ca(&mut self) -> &mut BasicConstraints {
60 self.ca = true;
61 self
62 }
63
64 /// Sets the pathlen to an optional non-negative value. The pathlen is the
65 /// maximum number of CAs that can appear below this one in a chain.
pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints66 pub fn pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints {
67 self.pathlen = Some(pathlen);
68 self
69 }
70
71 /// Return the `BasicConstraints` extension as an `X509Extension`.
build(&self) -> Result<X509Extension, ErrorStack>72 pub fn build(&self) -> Result<X509Extension, ErrorStack> {
73 let mut value = String::new();
74 if self.critical {
75 value.push_str("critical,");
76 }
77 value.push_str("CA:");
78 if self.ca {
79 value.push_str("TRUE");
80 } else {
81 value.push_str("FALSE");
82 }
83 if let Some(pathlen) = self.pathlen {
84 write!(value, ",pathlen:{}", pathlen).unwrap();
85 }
86 X509Extension::new_nid(None, None, Nid::BASIC_CONSTRAINTS, &value)
87 }
88 }
89
90 /// An extension consisting of a list of names of the permitted key usages.
91 pub struct KeyUsage {
92 critical: bool,
93 digital_signature: bool,
94 non_repudiation: bool,
95 key_encipherment: bool,
96 data_encipherment: bool,
97 key_agreement: bool,
98 key_cert_sign: bool,
99 crl_sign: bool,
100 encipher_only: bool,
101 decipher_only: bool,
102 }
103
104 impl Default for KeyUsage {
default() -> KeyUsage105 fn default() -> KeyUsage {
106 KeyUsage::new()
107 }
108 }
109
110 impl KeyUsage {
111 /// Construct a new `KeyUsage` extension.
new() -> KeyUsage112 pub fn new() -> KeyUsage {
113 KeyUsage {
114 critical: false,
115 digital_signature: false,
116 non_repudiation: false,
117 key_encipherment: false,
118 data_encipherment: false,
119 key_agreement: false,
120 key_cert_sign: false,
121 crl_sign: false,
122 encipher_only: false,
123 decipher_only: false,
124 }
125 }
126
127 /// Sets the `critical` flag to `true`. The extension will be critical.
critical(&mut self) -> &mut KeyUsage128 pub fn critical(&mut self) -> &mut KeyUsage {
129 self.critical = true;
130 self
131 }
132
133 /// Sets the `digitalSignature` flag to `true`.
digital_signature(&mut self) -> &mut KeyUsage134 pub fn digital_signature(&mut self) -> &mut KeyUsage {
135 self.digital_signature = true;
136 self
137 }
138
139 /// Sets the `nonRepudiation` flag to `true`.
non_repudiation(&mut self) -> &mut KeyUsage140 pub fn non_repudiation(&mut self) -> &mut KeyUsage {
141 self.non_repudiation = true;
142 self
143 }
144
145 /// Sets the `keyEncipherment` flag to `true`.
key_encipherment(&mut self) -> &mut KeyUsage146 pub fn key_encipherment(&mut self) -> &mut KeyUsage {
147 self.key_encipherment = true;
148 self
149 }
150
151 /// Sets the `dataEncipherment` flag to `true`.
data_encipherment(&mut self) -> &mut KeyUsage152 pub fn data_encipherment(&mut self) -> &mut KeyUsage {
153 self.data_encipherment = true;
154 self
155 }
156
157 /// Sets the `keyAgreement` flag to `true`.
key_agreement(&mut self) -> &mut KeyUsage158 pub fn key_agreement(&mut self) -> &mut KeyUsage {
159 self.key_agreement = true;
160 self
161 }
162
163 /// Sets the `keyCertSign` flag to `true`.
key_cert_sign(&mut self) -> &mut KeyUsage164 pub fn key_cert_sign(&mut self) -> &mut KeyUsage {
165 self.key_cert_sign = true;
166 self
167 }
168
169 /// Sets the `cRLSign` flag to `true`.
crl_sign(&mut self) -> &mut KeyUsage170 pub fn crl_sign(&mut self) -> &mut KeyUsage {
171 self.crl_sign = true;
172 self
173 }
174
175 /// Sets the `encipherOnly` flag to `true`.
encipher_only(&mut self) -> &mut KeyUsage176 pub fn encipher_only(&mut self) -> &mut KeyUsage {
177 self.encipher_only = true;
178 self
179 }
180
181 /// Sets the `decipherOnly` flag to `true`.
decipher_only(&mut self) -> &mut KeyUsage182 pub fn decipher_only(&mut self) -> &mut KeyUsage {
183 self.decipher_only = true;
184 self
185 }
186
187 /// Return the `KeyUsage` extension as an `X509Extension`.
build(&self) -> Result<X509Extension, ErrorStack>188 pub fn build(&self) -> Result<X509Extension, ErrorStack> {
189 let mut value = String::new();
190 let mut first = true;
191 append(&mut value, &mut first, self.critical, "critical");
192 append(
193 &mut value,
194 &mut first,
195 self.digital_signature,
196 "digitalSignature",
197 );
198 append(
199 &mut value,
200 &mut first,
201 self.non_repudiation,
202 "nonRepudiation",
203 );
204 append(
205 &mut value,
206 &mut first,
207 self.key_encipherment,
208 "keyEncipherment",
209 );
210 append(
211 &mut value,
212 &mut first,
213 self.data_encipherment,
214 "dataEncipherment",
215 );
216 append(&mut value, &mut first, self.key_agreement, "keyAgreement");
217 append(&mut value, &mut first, self.key_cert_sign, "keyCertSign");
218 append(&mut value, &mut first, self.crl_sign, "cRLSign");
219 append(&mut value, &mut first, self.encipher_only, "encipherOnly");
220 append(&mut value, &mut first, self.decipher_only, "decipherOnly");
221 X509Extension::new_nid(None, None, Nid::KEY_USAGE, &value)
222 }
223 }
224
225 /// An extension consisting of a list of usages indicating purposes
226 /// for which the certificate public key can be used for.
227 pub struct ExtendedKeyUsage {
228 critical: bool,
229 server_auth: bool,
230 client_auth: bool,
231 code_signing: bool,
232 email_protection: bool,
233 time_stamping: bool,
234 ms_code_ind: bool,
235 ms_code_com: bool,
236 ms_ctl_sign: bool,
237 ms_sgc: bool,
238 ms_efs: bool,
239 ns_sgc: bool,
240 other: Vec<String>,
241 }
242
243 impl Default for ExtendedKeyUsage {
default() -> ExtendedKeyUsage244 fn default() -> ExtendedKeyUsage {
245 ExtendedKeyUsage::new()
246 }
247 }
248
249 impl ExtendedKeyUsage {
250 /// Construct a new `ExtendedKeyUsage` extension.
new() -> ExtendedKeyUsage251 pub fn new() -> ExtendedKeyUsage {
252 ExtendedKeyUsage {
253 critical: false,
254 server_auth: false,
255 client_auth: false,
256 code_signing: false,
257 email_protection: false,
258 time_stamping: false,
259 ms_code_ind: false,
260 ms_code_com: false,
261 ms_ctl_sign: false,
262 ms_sgc: false,
263 ms_efs: false,
264 ns_sgc: false,
265 other: vec![],
266 }
267 }
268
269 /// Sets the `critical` flag to `true`. The extension will be critical.
critical(&mut self) -> &mut ExtendedKeyUsage270 pub fn critical(&mut self) -> &mut ExtendedKeyUsage {
271 self.critical = true;
272 self
273 }
274
275 /// Sets the `serverAuth` flag to `true`.
server_auth(&mut self) -> &mut ExtendedKeyUsage276 pub fn server_auth(&mut self) -> &mut ExtendedKeyUsage {
277 self.server_auth = true;
278 self
279 }
280
281 /// Sets the `clientAuth` flag to `true`.
client_auth(&mut self) -> &mut ExtendedKeyUsage282 pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage {
283 self.client_auth = true;
284 self
285 }
286
287 /// Sets the `codeSigning` flag to `true`.
code_signing(&mut self) -> &mut ExtendedKeyUsage288 pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage {
289 self.code_signing = true;
290 self
291 }
292
293 /// Sets the `emailProtection` flag to `true`.
email_protection(&mut self) -> &mut ExtendedKeyUsage294 pub fn email_protection(&mut self) -> &mut ExtendedKeyUsage {
295 self.email_protection = true;
296 self
297 }
298
299 /// Sets the `timeStamping` flag to `true`.
time_stamping(&mut self) -> &mut ExtendedKeyUsage300 pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage {
301 self.time_stamping = true;
302 self
303 }
304
305 /// Sets the `msCodeInd` flag to `true`.
ms_code_ind(&mut self) -> &mut ExtendedKeyUsage306 pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage {
307 self.ms_code_ind = true;
308 self
309 }
310
311 /// Sets the `msCodeCom` flag to `true`.
ms_code_com(&mut self) -> &mut ExtendedKeyUsage312 pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage {
313 self.ms_code_com = true;
314 self
315 }
316
317 /// Sets the `msCTLSign` flag to `true`.
ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage318 pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage {
319 self.ms_ctl_sign = true;
320 self
321 }
322
323 /// Sets the `msSGC` flag to `true`.
ms_sgc(&mut self) -> &mut ExtendedKeyUsage324 pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage {
325 self.ms_sgc = true;
326 self
327 }
328
329 /// Sets the `msEFS` flag to `true`.
ms_efs(&mut self) -> &mut ExtendedKeyUsage330 pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage {
331 self.ms_efs = true;
332 self
333 }
334
335 /// Sets the `nsSGC` flag to `true`.
ns_sgc(&mut self) -> &mut ExtendedKeyUsage336 pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage {
337 self.ns_sgc = true;
338 self
339 }
340
341 /// Sets a flag not already defined.
other(&mut self, other: &str) -> &mut ExtendedKeyUsage342 pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage {
343 self.other.push(other.to_owned());
344 self
345 }
346
347 /// Return the `ExtendedKeyUsage` extension as an `X509Extension`.
build(&self) -> Result<X509Extension, ErrorStack>348 pub fn build(&self) -> Result<X509Extension, ErrorStack> {
349 let mut value = String::new();
350 let mut first = true;
351 append(&mut value, &mut first, self.critical, "critical");
352 append(&mut value, &mut first, self.server_auth, "serverAuth");
353 append(&mut value, &mut first, self.client_auth, "clientAuth");
354 append(&mut value, &mut first, self.code_signing, "codeSigning");
355 append(
356 &mut value,
357 &mut first,
358 self.email_protection,
359 "emailProtection",
360 );
361 append(&mut value, &mut first, self.time_stamping, "timeStamping");
362 append(&mut value, &mut first, self.ms_code_ind, "msCodeInd");
363 append(&mut value, &mut first, self.ms_code_com, "msCodeCom");
364 append(&mut value, &mut first, self.ms_ctl_sign, "msCTLSign");
365 append(&mut value, &mut first, self.ms_sgc, "msSGC");
366 append(&mut value, &mut first, self.ms_efs, "msEFS");
367 append(&mut value, &mut first, self.ns_sgc, "nsSGC");
368 for other in &self.other {
369 append(&mut value, &mut first, true, other);
370 }
371 X509Extension::new_nid(None, None, Nid::EXT_KEY_USAGE, &value)
372 }
373 }
374
375 /// An extension that provides a means of identifying certificates that contain a
376 /// particular public key.
377 pub struct SubjectKeyIdentifier {
378 critical: bool,
379 }
380
381 impl Default for SubjectKeyIdentifier {
default() -> SubjectKeyIdentifier382 fn default() -> SubjectKeyIdentifier {
383 SubjectKeyIdentifier::new()
384 }
385 }
386
387 impl SubjectKeyIdentifier {
388 /// Construct a new `SubjectKeyIdentifier` extension.
new() -> SubjectKeyIdentifier389 pub fn new() -> SubjectKeyIdentifier {
390 SubjectKeyIdentifier { critical: false }
391 }
392
393 /// Sets the `critical` flag to `true`. The extension will be critical.
critical(&mut self) -> &mut SubjectKeyIdentifier394 pub fn critical(&mut self) -> &mut SubjectKeyIdentifier {
395 self.critical = true;
396 self
397 }
398
399 /// Return a `SubjectKeyIdentifier` extension as an `X509Extension`.
build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack>400 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 append(&mut value, &mut first, true, "hash");
405 X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_KEY_IDENTIFIER, &value)
406 }
407 }
408
409 /// An extension that provides a means of identifying the public key corresponding
410 /// to the private key used to sign a CRL.
411 pub struct AuthorityKeyIdentifier {
412 critical: bool,
413 keyid: Option<bool>,
414 issuer: Option<bool>,
415 }
416
417 impl Default for AuthorityKeyIdentifier {
default() -> AuthorityKeyIdentifier418 fn default() -> AuthorityKeyIdentifier {
419 AuthorityKeyIdentifier::new()
420 }
421 }
422
423 impl AuthorityKeyIdentifier {
424 /// Construct a new `AuthorityKeyIdentifier` extension.
new() -> AuthorityKeyIdentifier425 pub fn new() -> AuthorityKeyIdentifier {
426 AuthorityKeyIdentifier {
427 critical: false,
428 keyid: None,
429 issuer: None,
430 }
431 }
432
433 /// Sets the `critical` flag to `true`. The extension will be critical.
critical(&mut self) -> &mut AuthorityKeyIdentifier434 pub fn critical(&mut self) -> &mut AuthorityKeyIdentifier {
435 self.critical = true;
436 self
437 }
438
439 /// Sets the `keyid` flag.
keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier440 pub fn keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
441 self.keyid = Some(always);
442 self
443 }
444
445 /// Sets the `issuer` flag.
issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier446 pub fn issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
447 self.issuer = Some(always);
448 self
449 }
450
451 /// Return a `AuthorityKeyIdentifier` extension as an `X509Extension`.
build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack>452 pub fn build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack> {
453 let mut value = String::new();
454 let mut first = true;
455 append(&mut value, &mut first, self.critical, "critical");
456 match self.keyid {
457 Some(true) => append(&mut value, &mut first, true, "keyid:always"),
458 Some(false) => append(&mut value, &mut first, true, "keyid"),
459 None => {}
460 }
461 match self.issuer {
462 Some(true) => append(&mut value, &mut first, true, "issuer:always"),
463 Some(false) => append(&mut value, &mut first, true, "issuer"),
464 None => {}
465 }
466 X509Extension::new_nid(None, Some(ctx), Nid::AUTHORITY_KEY_IDENTIFIER, &value)
467 }
468 }
469
470 /// An extension that allows additional identities to be bound to the subject
471 /// of the certificate.
472 pub struct SubjectAlternativeName {
473 critical: bool,
474 names: Vec<String>,
475 }
476
477 impl Default for SubjectAlternativeName {
default() -> SubjectAlternativeName478 fn default() -> SubjectAlternativeName {
479 SubjectAlternativeName::new()
480 }
481 }
482
483 impl SubjectAlternativeName {
484 /// Construct a new `SubjectAlternativeName` extension.
new() -> SubjectAlternativeName485 pub fn new() -> SubjectAlternativeName {
486 SubjectAlternativeName {
487 critical: false,
488 names: vec![],
489 }
490 }
491
492 /// Sets the `critical` flag to `true`. The extension will be critical.
critical(&mut self) -> &mut SubjectAlternativeName493 pub fn critical(&mut self) -> &mut SubjectAlternativeName {
494 self.critical = true;
495 self
496 }
497
498 /// Sets the `email` flag.
email(&mut self, email: &str) -> &mut SubjectAlternativeName499 pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName {
500 self.names.push(format!("email:{}", email));
501 self
502 }
503
504 /// Sets the `uri` flag.
uri(&mut self, uri: &str) -> &mut SubjectAlternativeName505 pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName {
506 self.names.push(format!("URI:{}", uri));
507 self
508 }
509
510 /// Sets the `dns` flag.
dns(&mut self, dns: &str) -> &mut SubjectAlternativeName511 pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName {
512 self.names.push(format!("DNS:{}", dns));
513 self
514 }
515
516 /// Sets the `rid` flag.
rid(&mut self, rid: &str) -> &mut SubjectAlternativeName517 pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName {
518 self.names.push(format!("RID:{}", rid));
519 self
520 }
521
522 /// Sets the `ip` flag.
ip(&mut self, ip: &str) -> &mut SubjectAlternativeName523 pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName {
524 self.names.push(format!("IP:{}", ip));
525 self
526 }
527
528 /// Sets the `dirName` flag.
dir_name(&mut self, dir_name: &str) -> &mut SubjectAlternativeName529 pub fn dir_name(&mut self, dir_name: &str) -> &mut SubjectAlternativeName {
530 self.names.push(format!("dirName:{}", dir_name));
531 self
532 }
533
534 /// Sets the `otherName` flag.
other_name(&mut self, other_name: &str) -> &mut SubjectAlternativeName535 pub fn other_name(&mut self, other_name: &str) -> &mut SubjectAlternativeName {
536 self.names.push(format!("otherName:{}", other_name));
537 self
538 }
539
540 /// Return a `SubjectAlternativeName` extension as an `X509Extension`.
build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack>541 pub fn build(&self, ctx: &X509v3Context) -> Result<X509Extension, ErrorStack> {
542 let mut value = String::new();
543 let mut first = true;
544 append(&mut value, &mut first, self.critical, "critical");
545 for name in &self.names {
546 append(&mut value, &mut first, true, name);
547 }
548 X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_ALT_NAME, &value)
549 }
550 }
551
append(value: &mut String, first: &mut bool, should: bool, element: &str)552 fn append(value: &mut String, first: &mut bool, should: bool, element: &str) {
553 if !should {
554 return;
555 }
556
557 if !*first {
558 value.push(',');
559 }
560 *first = false;
561 value.push_str(element);
562 }
563