Botan 3.0.0
Crypto and TLS for C&
x509self.cpp
Go to the documentation of this file.
1/*
2* PKCS #10/Self Signed Cert Creation
3* (C) 1999-2008,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/x509self.h>
9#include <botan/x509_key.h>
10#include <botan/x509_ext.h>
11#include <botan/x509_ca.h>
12#include <botan/der_enc.h>
13#include <botan/pubkey.h>
14#include <botan/hash.h>
15
16namespace Botan {
17
18namespace {
19
20/*
21* Load information from the X509_Cert_Options
22*/
23void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn,
24 AlternativeName& subject_alt)
25 {
26 subject_dn.add_attribute("X520.CommonName", opts.common_name);
27 subject_dn.add_attribute("X520.Country", opts.country);
28 subject_dn.add_attribute("X520.State", opts.state);
29 subject_dn.add_attribute("X520.Locality", opts.locality);
30 subject_dn.add_attribute("X520.Organization", opts.organization);
31 subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
32 for(const auto& extra_ou : opts.more_org_units) {
33 subject_dn.add_attribute("X520.OrganizationalUnit", extra_ou);
34 }
35
36 subject_dn.add_attribute("X520.SerialNumber", opts.serial_number);
37 subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip);
38 subject_alt.add_othername(OID::from_string("PKIX.XMPPAddr"),
39 opts.xmpp, ASN1_Type::Utf8String);
40
41 for(const auto& dns : opts.more_dns)
42 subject_alt.add_attribute("DNS", dns);
43 }
44}
45
46namespace X509 {
47
48/*
49* Create a new self-signed X.509 certificate
50*/
52 const Private_Key& key,
53 std::string_view hash_fn,
55 {
56 const std::vector<uint8_t> pub_key = X509::BER_encode(key);
57 auto signer = X509_Object::choose_sig_format(key, rng, hash_fn, opts.padding_scheme);
58 const AlgorithmIdentifier sig_algo = signer->algorithm_identifier();
59 BOTAN_ASSERT_NOMSG(sig_algo.oid().has_value());
60
61 X509_DN subject_dn;
62 AlternativeName subject_alt;
63 load_info(opts, subject_dn, subject_alt);
64
65 Extensions extensions = opts.extensions;
66
67 const auto constraints =
69
70 if(!constraints.compatible_with(key))
71 throw Invalid_Argument("The requested key constraints are incompatible with the algorithm");
72
73 extensions.add_new(
74 std::make_unique<Cert_Extension::Basic_Constraints>(opts.is_CA, opts.path_limit),
75 true);
76
77 if(!constraints.empty())
78 {
79 extensions.add_new(std::make_unique<Cert_Extension::Key_Usage>(constraints), true);
80 }
81
82 auto skid = std::make_unique<Cert_Extension::Subject_Key_ID>(pub_key, signer->hash_function());
83
84 extensions.add_new(std::make_unique<Cert_Extension::Authority_Key_ID>(skid->get_key_id()));
85 extensions.add_new(std::move(skid));
86
87 extensions.add_new(
88 std::make_unique<Cert_Extension::Subject_Alternative_Name>(subject_alt));
89
90 extensions.add_new(
91 std::make_unique<Cert_Extension::Extended_Key_Usage>(opts.ex_constraints));
92
93 return X509_CA::make_cert(*signer, rng, sig_algo, pub_key,
94 opts.start, opts.end,
95 subject_dn, subject_dn,
96 extensions);
97 }
98
99/*
100* Create a PKCS #10 certificate request
101*/
103 const Private_Key& key,
104 std::string_view hash_fn,
106 {
107 X509_DN subject_dn;
108 AlternativeName subject_alt;
109 load_info(opts, subject_dn, subject_alt);
110
111 const auto constraints =
113
114 if(!constraints.compatible_with(key))
115 throw Invalid_Argument("The requested key constraints are incompatible with the algorithm");
116
117 Extensions extensions = opts.extensions;
118
119 extensions.add_new(std::make_unique<Cert_Extension::Basic_Constraints>(opts.is_CA, opts.path_limit));
120
121 if(!constraints.empty())
122 {
123 extensions.add_new(std::make_unique<Cert_Extension::Key_Usage>(constraints));
124 }
125
126 extensions.add_new(std::make_unique<Cert_Extension::Extended_Key_Usage>(opts.ex_constraints));
127 extensions.add_new(std::make_unique<Cert_Extension::Subject_Alternative_Name>(subject_alt));
128
129 return PKCS10_Request::create(key,
130 subject_dn,
131 extensions,
132 hash_fn,
133 rng,
134 opts.padding_scheme,
135 opts.challenge);
136 }
137
138}
139
140}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
const OID & oid() const
Definition: asn1_obj.h:477
bool add_new(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition: x509_ext.cpp:133
static Key_Constraints ca_constraints()
Definition: pkix_enums.h:149
bool has_value() const
Definition: asn1_obj.h:286
static OID from_string(std::string_view str)
Definition: asn1_oid.cpp:78
static PKCS10_Request create(const Private_Key &key, const X509_DN &subject_dn, const Extensions &extensions, std::string_view hash_fn, RandomNumberGenerator &rng, std::string_view padding_scheme="", std::string_view challenge="")
Definition: pkcs10.cpp:58
static X509_Certificate make_cert(PK_Signer &signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &sig_algo, const std::vector< uint8_t > &pub_key, const X509_Time &not_before, const X509_Time &not_after, const X509_DN &issuer_dn, const X509_DN &subject_dn, const Extensions &extensions)
Definition: x509_ca.cpp:104
std::vector< OID > ex_constraints
Definition: x509self.h:130
Key_Constraints constraints
Definition: x509self.h:125
std::string challenge
Definition: x509self.h:99
std::string padding_scheme
Definition: x509self.h:120
static std::unique_ptr< PK_Signer > choose_sig_format(const Private_Key &key, RandomNumberGenerator &rng, std::string_view hash_fn, std::string_view padding_algo)
Definition: x509_obj.cpp:244
PKCS10_Request create_cert_req(const X509_Cert_Options &opts, const Private_Key &key, std::string_view hash_fn, RandomNumberGenerator &rng)
Definition: x509self.cpp:102
std::vector< uint8_t > BER_encode(const Public_Key &key)
Definition: x509_key.h:28
X509_Certificate create_self_signed_cert(const X509_Cert_Options &opts, const Private_Key &key, std::string_view hash_fn, RandomNumberGenerator &rng)
Definition: x509self.cpp:51
Definition: alg_id.cpp:12