Botan 3.3.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
10#include <botan/der_enc.h>
11#include <botan/hash.h>
12#include <botan/pubkey.h>
13#include <botan/x509_ca.h>
14#include <botan/x509_ext.h>
15#include <botan/x509_key.h>
16
17namespace Botan {
18
19namespace {
20
21/*
22* Load information from the X509_Cert_Options
23*/
24void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn, AlternativeName& subject_alt) {
25 subject_dn.add_attribute("X520.CommonName", opts.common_name);
26 subject_dn.add_attribute("X520.Country", opts.country);
27 subject_dn.add_attribute("X520.State", opts.state);
28 subject_dn.add_attribute("X520.Locality", opts.locality);
29 subject_dn.add_attribute("X520.Organization", opts.organization);
30 subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
31 for(const auto& extra_ou : opts.more_org_units) {
32 subject_dn.add_attribute("X520.OrganizationalUnit", extra_ou);
33 }
34
35 subject_dn.add_attribute("X520.SerialNumber", opts.serial_number);
36 subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip);
37 subject_alt.add_othername(OID::from_string("PKIX.XMPPAddr"), opts.xmpp, ASN1_Type::Utf8String);
38
39 for(const auto& dns : opts.more_dns) {
40 subject_alt.add_attribute("DNS", dns);
41 }
42}
43} // namespace
44
45namespace X509 {
46
47/*
48* Create a new self-signed X.509 certificate
49*/
51 const Private_Key& key,
52 std::string_view hash_fn,
54 const std::vector<uint8_t> pub_key = X509::BER_encode(key);
55 auto signer = X509_Object::choose_sig_format(key, rng, hash_fn, opts.padding_scheme);
56 const AlgorithmIdentifier sig_algo = signer->algorithm_identifier();
57 BOTAN_ASSERT_NOMSG(sig_algo.oid().has_value());
58
59 X509_DN subject_dn;
60 AlternativeName subject_alt;
61 load_info(opts, subject_dn, subject_alt);
62
63 Extensions extensions = opts.extensions;
64
65 const auto constraints = opts.is_CA ? Key_Constraints::ca_constraints() : opts.constraints;
66
67 if(!constraints.compatible_with(key)) {
68 throw Invalid_Argument("The requested key constraints are incompatible with the algorithm");
69 }
70
71 extensions.add_new(std::make_unique<Cert_Extension::Basic_Constraints>(opts.is_CA, opts.path_limit), true);
72
73 if(!constraints.empty()) {
74 extensions.add_new(std::make_unique<Cert_Extension::Key_Usage>(constraints), true);
75 }
76
77 auto skid = std::make_unique<Cert_Extension::Subject_Key_ID>(pub_key, signer->hash_function());
78
79 extensions.add_new(std::make_unique<Cert_Extension::Authority_Key_ID>(skid->get_key_id()));
80 extensions.add_new(std::move(skid));
81
82 extensions.add_new(std::make_unique<Cert_Extension::Subject_Alternative_Name>(subject_alt));
83
84 extensions.add_new(std::make_unique<Cert_Extension::Extended_Key_Usage>(opts.ex_constraints));
85
86 return X509_CA::make_cert(*signer, rng, sig_algo, pub_key, opts.start, opts.end, subject_dn, subject_dn, extensions);
87}
88
89/*
90* Create a PKCS #10 certificate request
91*/
93 const Private_Key& key,
94 std::string_view hash_fn,
96 X509_DN subject_dn;
97 AlternativeName subject_alt;
98 load_info(opts, subject_dn, subject_alt);
99
100 const auto constraints = opts.is_CA ? Key_Constraints::ca_constraints() : opts.constraints;
101
102 if(!constraints.compatible_with(key)) {
103 throw Invalid_Argument("The requested key constraints are incompatible with the algorithm");
104 }
105
106 Extensions extensions = opts.extensions;
107
108 extensions.add_new(std::make_unique<Cert_Extension::Basic_Constraints>(opts.is_CA, opts.path_limit));
109
110 if(!constraints.empty()) {
111 extensions.add_new(std::make_unique<Cert_Extension::Key_Usage>(constraints));
112 }
113
114 extensions.add_new(std::make_unique<Cert_Extension::Extended_Key_Usage>(opts.ex_constraints));
115 extensions.add_new(std::make_unique<Cert_Extension::Subject_Alternative_Name>(subject_alt));
116
117 return PKCS10_Request::create(key, subject_dn, extensions, hash_fn, rng, opts.padding_scheme, opts.challenge);
118}
119
120} // namespace X509
121
122} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
const OID & oid() const
Definition asn1_obj.h:455
bool add_new(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:137
static Key_Constraints ca_constraints()
Definition pkix_enums.h:149
bool has_value() const
Definition asn1_obj.h:271
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:74
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:53
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:106
std::vector< OID > ex_constraints
Definition x509self.h:129
Key_Constraints constraints
Definition x509self.h:124
std::string challenge
Definition x509self.h:98
std::string padding_scheme
Definition x509self.h:119
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:209
PKCS10_Request create_cert_req(const X509_Cert_Options &opts, const Private_Key &key, std::string_view hash_fn, RandomNumberGenerator &rng)
Definition x509self.cpp:92
std::vector< uint8_t > BER_encode(const Public_Key &key)
Definition x509_key.h:23
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:50