8#include <botan/pkcs10.h>
10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
13#include <botan/pubkey.h>
14#include <botan/x509_ext.h>
15#include <botan/x509_key.h>
16#include <botan/x509cert.h>
20class PKCS10_Data final {
23 std::vector<uint8_t> m_public_key_bits;
24 AlternativeName m_alt_name;
25 std::string m_challenge;
26 Extensions m_extensions;
30 return "CERTIFICATE REQUEST";
34 return {
"NEW CERTIFICATE REQUEST"};
46#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
57 std::string_view hash_fn,
59 std::string_view padding_scheme,
60 std::string_view challenge) {
64 const size_t PKCS10_VERSION = 0;
74 if(!challenge.empty()) {
75 std::vector<uint8_t> value;
80 std::vector<uint8_t> extension_req;
97std::unique_ptr<PKCS10_Data> decode_pkcs10(
const std::vector<uint8_t>& body) {
98 auto data = std::make_unique<PKCS10_Data>();
103 cert_req_info.decode(version);
105 throw Decoding_Error(
"Unknown version code in PKCS #10 request: " + std::to_string(version));
108 cert_req_info.decode(data->m_subject_dn);
110 const BER_Object public_key = cert_req_info.get_next_object();
112 throw BER_Bad_Tag(
"PKCS10_Request: Unexpected tag for public key", public_key.tagging());
117 const BER_Object attr_bits = cert_req_info.get_next_object();
119 std::set<std::string> pkcs9_email;
122 BER_Decoder attributes(attr_bits, cert_req_info.limits());
123 while(attributes.more_items()) {
125 attributes.decode(attr);
127 const OID& oid = attr.object_identifier();
128 BER_Decoder value(attr.get_parameters(), cert_req_info.limits());
133 pkcs9_email.insert(email.value());
136 value.decode(challenge_password);
137 data->m_challenge = challenge_password.
value();
139 value.decode(data->m_extensions).verify_end();
142 attributes.verify_end();
143 }
else if(attr_bits.is_set()) {
144 throw BER_Bad_Tag(
"PKCS10_Request: Unexpected tag for attributes", attr_bits.tagging());
147 cert_req_info.verify_end();
150 data->m_alt_name = ext->get_alt_name();
153 for(
const auto& email : pkcs9_email) {
154 data->m_alt_name.add_email(email);
162void PKCS10_Request::force_decode() {
169 throw Decoding_Error(
"PKCS #10 request: Bad signature detected");
173const PKCS10_Data& PKCS10_Request::data()
const {
174 if(m_data ==
nullptr) {
175 throw Decoding_Error(
"PKCS10_Request decoding failed");
184 return data().m_challenge;
191 return data().m_subject_dn;
198 return data().m_public_key_bits;
213 return data().m_alt_name;
220 return data().m_extensions;
227 if(
const auto* ext =
extensions().get_extension_object_as<Cert_Extension::Key_Usage>()) {
228 return ext->get_constraints();
238 if(
const auto* ext =
extensions().get_extension_object_as<Cert_Extension::Extended_Key_Usage>()) {
239 return ext->object_identifiers();
249 if(
const auto* ext =
extensions().get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
260 if(
const auto* ext =
extensions().get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
262 return ext->path_length_constraint();
const std::string & value() const
DER_Encoder & end_explicit()
DER_Encoder & start_explicit(uint16_t type_tag)
DER_Encoder & start_sequence()
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
std::vector< uint8_t > get_contents_unlocked()
DER_Encoder & encode(bool b)
static OID from_string(std::string_view str)
PKCS10_Request(DataSource &source)
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="")
std::unique_ptr< Public_Key > subject_public_key() const
const X509_DN & subject_dn() const
std::vector< OID > ex_constraints() const
const std::vector< uint8_t > & raw_public_key() const
Key_Constraints constraints() const
const AlternativeName & subject_alt_name() const
std::optional< size_t > path_length_constraint() const
const Extensions & extensions() const
std::string challenge_password() const
std::vector< uint8_t > subject_public_key() const
const std::vector< uint8_t > & signed_body() const
virtual std::vector< std::string > alternate_PEM_labels() const
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)
static std::vector< uint8_t > make_signed(PK_Signer &signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, std::span< const uint8_t > tbs)
void load_data(DataSource &src)
virtual std::string PEM_label() const =0
bool check_signature(const Public_Key &key) const
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
std::unique_ptr< Public_Key > load_key(DataSource &source)