Botan 3.1.1
Crypto and TLS for C&
pkcs10.cpp
Go to the documentation of this file.
1/*
2* PKCS #10
3* (C) 1999-2007,2017 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/pkcs10.h>
9
10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
12#include <botan/pem.h>
13#include <botan/pubkey.h>
14#include <botan/x509_ext.h>
15#include <botan/x509_key.h>
16#include <botan/x509cert.h>
17
18namespace Botan {
19
20struct PKCS10_Data {
21 X509_DN m_subject_dn;
22 std::vector<uint8_t> m_public_key_bits;
23 AlternativeName m_alt_name;
24 std::string m_challenge;
25 Extensions m_extensions;
26};
27
28std::string PKCS10_Request::PEM_label() const {
29 return "CERTIFICATE REQUEST";
30}
31
32std::vector<std::string> PKCS10_Request::alternate_PEM_labels() const {
33 return {"NEW CERTIFICATE REQUEST"};
34}
35
37 load_data(src);
38}
39
40PKCS10_Request::PKCS10_Request(const std::vector<uint8_t>& vec) {
41 DataSource_Memory src(vec.data(), vec.size());
42 load_data(src);
43}
44
45#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
46PKCS10_Request::PKCS10_Request(std::string_view fsname) {
47 DataSource_Stream src(fsname, true);
48 load_data(src);
49}
50#endif
51
52//static
54 const X509_DN& subject_dn,
55 const Extensions& extensions,
56 std::string_view hash_fn,
58 std::string_view padding_scheme,
59 std::string_view challenge) {
60 auto signer = choose_sig_format(key, rng, hash_fn, padding_scheme);
61 const AlgorithmIdentifier sig_algo = signer->algorithm_identifier();
62
63 const size_t PKCS10_VERSION = 0;
64
65 DER_Encoder tbs_req;
66
67 tbs_req.start_sequence()
68 .encode(PKCS10_VERSION)
72
73 if(challenge.empty() == false) {
74 std::vector<uint8_t> value;
75 DER_Encoder(value).encode(ASN1_String(challenge));
76 tbs_req.encode(Attribute("PKCS9.ChallengePassword", value));
77 }
78
79 std::vector<uint8_t> extension_req;
81 tbs_req.encode(Attribute("PKCS9.ExtensionRequest", extension_req));
82
83 // end the start_explicit above
84 tbs_req.end_explicit().end_cons();
85
86 const std::vector<uint8_t> req = X509_Object::make_signed(*signer, rng, sig_algo, tbs_req.get_contents());
87
88 return PKCS10_Request(req);
89}
90
91/*
92* Decode the CertificateRequestInfo
93*/
94namespace {
95
96std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body) {
97 auto data = std::make_unique<PKCS10_Data>();
98
99 BER_Decoder cert_req_info(body);
100
101 size_t version;
102 cert_req_info.decode(version);
103 if(version != 0) {
104 throw Decoding_Error("Unknown version code in PKCS #10 request: " + std::to_string(version));
105 }
106
107 cert_req_info.decode(data->m_subject_dn);
108
109 BER_Object public_key = cert_req_info.get_next_object();
110 if(public_key.is_a(ASN1_Type::Sequence, ASN1_Class::Constructed) == false) {
111 throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", public_key.tagging());
112 }
113
114 data->m_public_key_bits = ASN1::put_in_sequence(public_key.bits(), public_key.length());
115
116 BER_Object attr_bits = cert_req_info.get_next_object();
117
118 std::set<std::string> pkcs9_email;
119
121 BER_Decoder attributes(attr_bits);
122 while(attributes.more_items()) {
123 Attribute attr;
124 attributes.decode(attr);
125
126 const OID& oid = attr.object_identifier();
127 BER_Decoder value(attr.get_parameters());
128
129 if(oid == OID::from_string("PKCS9.EmailAddress")) {
130 ASN1_String email;
131 value.decode(email);
132 pkcs9_email.insert(email.value());
133 } else if(oid == OID::from_string("PKCS9.ChallengePassword")) {
134 ASN1_String challenge_password;
135 value.decode(challenge_password);
136 data->m_challenge = challenge_password.value();
137 } else if(oid == OID::from_string("PKCS9.ExtensionRequest")) {
138 value.decode(data->m_extensions).verify_end();
139 }
140 }
141 attributes.verify_end();
142 } else if(attr_bits.is_set()) {
143 throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", attr_bits.tagging());
144 }
145
146 cert_req_info.verify_end();
147
148 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
149 data->m_alt_name = ext->get_alt_name();
150 }
151
152 for(const auto& email : pkcs9_email) {
153 data->m_alt_name.add_attribute("RFC882", email);
154 }
155
156 return data;
157}
158
159} // namespace
160
161void PKCS10_Request::force_decode() {
162 m_data.reset();
163
164 m_data = decode_pkcs10(signed_body());
165
166 auto key = this->subject_public_key();
167 if(!this->check_signature(*key)) {
168 throw Decoding_Error("PKCS #10 request: Bad signature detected");
169 }
170}
171
172const PKCS10_Data& PKCS10_Request::data() const {
173 if(m_data == nullptr) {
174 throw Decoding_Error("PKCS10_Request decoding failed");
175 }
176 return *m_data;
177}
178
179/*
180* Return the challenge password (if any)
181*/
183 return data().m_challenge;
184}
185
186/*
187* Return the name of the requestor
188*/
190 return data().m_subject_dn;
191}
192
193/*
194* Return the public key of the requestor
195*/
196const std::vector<uint8_t>& PKCS10_Request::raw_public_key() const {
197 return data().m_public_key_bits;
198}
199
200/*
201* Return the public key of the requestor
202*/
203std::unique_ptr<Public_Key> PKCS10_Request::subject_public_key() const {
205 return X509::load_key(source);
206}
207
208/*
209* Return the alternative names of the requestor
210*/
212 return data().m_alt_name;
213}
214
215/*
216* Return the X509v3 extensions
217*/
219 return data().m_extensions;
220}
221
222/*
223* Return the key constraints (if any)
224*/
226 if(auto ext = extensions().get(OID::from_string("X509v3.KeyUsage"))) {
227 return dynamic_cast<Cert_Extension::Key_Usage&>(*ext).get_constraints();
228 }
229
231}
232
233/*
234* Return the extendend key constraints (if any)
235*/
236std::vector<OID> PKCS10_Request::ex_constraints() const {
237 if(auto ext = extensions().get(OID::from_string("X509v3.ExtendedKeyUsage"))) {
238 return dynamic_cast<Cert_Extension::Extended_Key_Usage&>(*ext).object_identifiers();
239 }
240
241 return {};
242}
243
244/*
245* Return is a CA certificate is requested
246*/
248 if(auto ext = extensions().get(OID::from_string("X509v3.BasicConstraints"))) {
249 return dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext).get_is_ca();
250 }
251
252 return false;
253}
254
255/*
256* Return the desired path limit (if any)
257*/
259 if(auto ext = extensions().get(OID::from_string("X509v3.BasicConstraints"))) {
260 Cert_Extension::Basic_Constraints& basic_constraints = dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext);
261 if(basic_constraints.get_is_ca()) {
262 return basic_constraints.get_path_limit();
263 }
264 }
265
266 return 0;
267}
268
269} // namespace Botan
const std::vector< OID > & object_identifiers() const
Definition: x509_ext.h:212
Key_Constraints get_constraints() const
Definition: x509_ext.h:64
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:132
DER_Encoder & end_explicit()
Definition: der_enc.cpp:200
DER_Encoder & start_explicit(uint16_t type_tag)
Definition: der_enc.cpp:186
DER_Encoder & start_sequence()
Definition: der_enc.h:65
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:207
DER_Encoder & end_cons()
Definition: der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:250
static OID from_string(std::string_view str)
Definition: asn1_oid.cpp:74
PKCS10_Request(DataSource &source)
Definition: pkcs10.cpp:36
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
std::unique_ptr< Public_Key > subject_public_key() const
Definition: pkcs10.cpp:203
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:189
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:236
size_t path_limit() const
Definition: pkcs10.cpp:258
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:196
Key_Constraints constraints() const
Definition: pkcs10.cpp:225
bool is_CA() const
Definition: pkcs10.cpp:247
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:211
const Extensions & extensions() const
Definition: pkcs10.cpp:218
std::string challenge_password() const
Definition: pkcs10.cpp:182
std::vector< uint8_t > subject_public_key() const
Definition: pk_keys.cpp:48
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:42
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
static std::vector< uint8_t > make_signed(PK_Signer &signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &tbs)
Definition: x509_obj.cpp:125
void load_data(DataSource &src)
Definition: x509_obj.cpp:24
bool check_signature(const Public_Key &key) const
Definition: x509_obj.cpp:97
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:171
CK_ATTRIBUTE Attribute
Definition: p11.h:823
std::unique_ptr< Public_Key > load_key(DataSource &source)
Definition: x509_key.cpp:28
Definition: alg_id.cpp:13