8#include <botan/x509self.h>
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#include <botan/internal/fmt.h>
17#include <botan/internal/parsing.h>
26X509_DN load_dn_info(
const X509_Cert_Options& opts) {
29 subject_dn.add_attribute(
"X520.CommonName", opts.common_name);
30 subject_dn.add_attribute(
"X520.Country", opts.country);
31 subject_dn.add_attribute(
"X520.State", opts.state);
32 subject_dn.add_attribute(
"X520.Locality", opts.locality);
33 subject_dn.add_attribute(
"X520.Organization", opts.organization);
34 subject_dn.add_attribute(
"X520.OrganizationalUnit", opts.org_unit);
35 subject_dn.add_attribute(
"X520.SerialNumber", opts.serial_number);
37 for(
const auto& extra_ou : opts.more_org_units) {
38 subject_dn.add_attribute(
"X520.OrganizationalUnit", extra_ou);
44auto create_alt_name_ext(
const X509_Cert_Options& opts, Extensions& extensions) {
45 AlternativeName subject_alt;
51 if(
auto ext = extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
52 subject_alt = ext->get_alt_name();
55 subject_alt.add_dns(opts.dns);
56 for(
const auto& nm : opts.more_dns) {
57 subject_alt.add_dns(nm);
59 subject_alt.add_uri(opts.uri);
60 subject_alt.add_email(opts.email);
61 if(!opts.ip.empty()) {
63 subject_alt.add_ipv4_address(*ipv4);
65 throw Invalid_Argument(
fmt(
"Invalid IPv4 address '{}'", opts.ip));
69 if(!opts.xmpp.empty()) {
73 return std::make_unique<Cert_Extension::Subject_Alternative_Name>(subject_alt);
85 std::string_view hash_fn,
92 const auto subject_dn = load_dn_info(opts);
98 if(!constraints.compatible_with(key)) {
99 throw Invalid_Argument(
"The requested key constraints are incompatible with the algorithm");
102 extensions.
add_new(std::make_unique<Cert_Extension::Basic_Constraints>(opts.
is_CA, opts.
path_limit),
true);
104 if(!constraints.empty()) {
105 extensions.
add_new(std::make_unique<Cert_Extension::Key_Usage>(constraints),
true);
108 auto skid = std::make_unique<Cert_Extension::Subject_Key_ID>(pub_key, signer->hash_function());
110 extensions.
add_new(std::make_unique<Cert_Extension::Authority_Key_ID>(skid->get_key_id()));
111 extensions.
add_new(std::move(skid));
113 extensions.
replace(create_alt_name_ext(opts, extensions));
125 std::string_view hash_fn,
127 const auto subject_dn = load_dn_info(opts);
131 if(!constraints.compatible_with(key)) {
132 throw Invalid_Argument(
"The requested key constraints are incompatible with the algorithm");
139 if(!constraints.empty()) {
140 extensions.
add_new(std::make_unique<Cert_Extension::Key_Usage>(constraints));
143 extensions.
replace(create_alt_name_ext(opts, extensions));
145 create_alt_name_ext(opts, extensions);
#define BOTAN_ASSERT_NOMSG(expr)
void replace(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
bool add_new(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
static Key_Constraints ca_constraints()
static OID from_string(std::string_view str)
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="")
static X509_Certificate make_cert(PK_Signer &signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &sig_algo, const std::vector< uint8_t > &pub_key, const X509_Time ¬_before, const X509_Time ¬_after, const X509_DN &issuer_dn, const X509_DN &subject_dn, const Extensions &extensions)
std::vector< OID > ex_constraints
Key_Constraints constraints
std::string padding_scheme
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)
PKCS10_Request create_cert_req(const X509_Cert_Options &opts, const Private_Key &key, std::string_view hash_fn, RandomNumberGenerator &rng)
std::vector< uint8_t > BER_encode(const Public_Key &key)
X509_Certificate create_self_signed_cert(const X509_Cert_Options &opts, const Private_Key &key, std::string_view hash_fn, RandomNumberGenerator &rng)
std::string fmt(std::string_view format, const T &... args)
std::optional< uint32_t > string_to_ipv4(std::string_view str)