Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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 #include <botan/x509_ext.h>
10 #include <botan/x509cert.h>
11 #include <botan/ber_dec.h>
12 #include <botan/der_enc.h>
13 #include <botan/pubkey.h>
14 #include <botan/oids.h>
15 #include <botan/pem.h>
16
17 namespace Botan {
18
19 struct PKCS10_Data
20 {
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
28 std::string PKCS10_Request::PEM_label() const
29 {
30 return "CERTIFICATE REQUEST";
31 }
32
33 std::vector<std::string> PKCS10_Request::alternate_PEM_labels() const
34 {
35 return { "NEW CERTIFICATE REQUEST" };
36 }
37
38 PKCS10_Request::PKCS10_Request(DataSource& src)
39 {
40 load_data(src);
41 }
42
43 PKCS10_Request::PKCS10_Request(const std::vector<uint8_t>& vec)
44 {
45 DataSource_Memory src(vec.data(), vec.size());
46 load_data(src);
47 }
48
49 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
50 PKCS10_Request::PKCS10_Request(const std::string& fsname)
51 {
52 DataSource_Stream src(fsname, true);
53 load_data(src);
54 }
55 #endif
56
57 //static
58 PKCS10_Request PKCS10_Request::create(const Private_Key& key,
59 const X509_DN& subject_dn,
60 const Extensions& extensions,
61 const std::string& hash_fn,
62 RandomNumberGenerator& rng,
63 const std::string& padding_scheme,
64 const std::string& challenge)
65 {
66 const std::map<std::string,std::string> sig_opts = { {"padding", padding_scheme} };
67
68 AlgorithmIdentifier sig_algo;
69 std::unique_ptr<PK_Signer> signer = choose_sig_format(sig_algo, key, rng, hash_fn, padding_scheme);
70
71 const size_t PKCS10_VERSION = 0;
72
73 DER_Encoder tbs_req;
74
75 tbs_req.start_cons(SEQUENCE)
76 .encode(PKCS10_VERSION)
77 .encode(subject_dn)
78 .raw_bytes(key.subject_public_key())
79 .start_explicit(0);
80
81 if(challenge.empty() == false)
82 {
83 std::vector<uint8_t> value;
84 DER_Encoder(value).encode(ASN1_String(challenge, DIRECTORY_STRING));
85 tbs_req.encode(Attribute("PKCS9.ChallengePassword", value));
86 }
87
88 std::vector<uint8_t> extension_req;
89 DER_Encoder(extension_req).start_cons(SEQUENCE).encode(extensions).end_cons();
90 tbs_req.encode(Attribute("PKCS9.ExtensionRequest", extension_req));
91
92 // end the start_explicit above
93 tbs_req.end_explicit().end_cons();
94
95 const std::vector<uint8_t> req =
96 X509_Object::make_signed(signer.get(), rng, sig_algo,
97 tbs_req.get_contents());
98
99 return PKCS10_Request(req);
100 }
101
102 /*
103 * Decode the CertificateRequestInfo
104 */
105 namespace {
106
107 std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body)
108 {
109 std::unique_ptr<PKCS10_Data> data(new PKCS10_Data);
110
111 BER_Decoder cert_req_info(body);
112
113 size_t version;
114 cert_req_info.decode(version);
115 if(version != 0)
116 throw Decoding_Error("Unknown version code in PKCS #10 request: " +
117 std::to_string(version));
118
119 cert_req_info.decode(data->m_subject_dn);
120
121 BER_Object public_key = cert_req_info.get_next_object();
122 if(public_key.is_a(SEQUENCE, CONSTRUCTED) == false)
123 throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", public_key.tagging());
124
125 data->m_public_key_bits = ASN1::put_in_sequence(public_key.bits(), public_key.length());
126
127 BER_Object attr_bits = cert_req_info.get_next_object();
128
129 std::set<std::string> pkcs9_email;
130
131 if(attr_bits.is_a(0, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)))
132 {
133 BER_Decoder attributes(attr_bits);
134 while(attributes.more_items())
135 {
136 Attribute attr;
137 attributes.decode(attr);
138
139 const OID& oid = attr.get_oid();
140 BER_Decoder value(attr.get_parameters());
141
142 if(oid == OID::from_string("PKCS9.EmailAddress"))
143 {
144 ASN1_String email;
145 value.decode(email);
146 pkcs9_email.insert(email.value());
147 }
148 else if(oid == OID::from_string("PKCS9.ChallengePassword"))
149 {
150 ASN1_String challenge_password;
151 value.decode(challenge_password);
152 data->m_challenge = challenge_password.value();
153 }
154 else if(oid == OID::from_string("PKCS9.ExtensionRequest"))
155 {
156 value.decode(data->m_extensions).verify_end();
157 }
158 }
159 attributes.verify_end();
160 }
161 else if(attr_bits.is_set())
162 throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", attr_bits.tagging());
163
164 cert_req_info.verify_end();
165
166 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>())
167 {
168 data->m_alt_name = ext->get_alt_name();
169 }
170
171 for(std::string email : pkcs9_email)
172 {
173 data->m_alt_name.add_attribute("RFC882", email);
174 }
175
176 return data;
177 }
178
179 }
180
181 void PKCS10_Request::force_decode()
182 {
183 m_data.reset();
184
185 std::unique_ptr<PKCS10_Data> data = decode_pkcs10(signed_body());
186
187 m_data.reset(data.release());
188
189 if(!this->check_signature(subject_public_key()))
190 throw Decoding_Error("PKCS #10 request: Bad signature detected");
191 }
192
193 const PKCS10_Data& PKCS10_Request::data() const
194 {
195 if(m_data == nullptr)
196 throw Decoding_Error("PKCS10_Request decoding failed");
197 return *m_data.get();
198 }
199
200 /*
201 * Return the challenge password (if any)
202 */
203 std::string PKCS10_Request::challenge_password() const
204 {
205 return data().m_challenge;
206 }
207
208 /*
209 * Return the name of the requestor
210 */
211 const X509_DN& PKCS10_Request::subject_dn() const
212 {
213 return data().m_subject_dn;
214 }
215
216 /*
217 * Return the public key of the requestor
218 */
219 const std::vector<uint8_t>& PKCS10_Request::raw_public_key() const
220 {
221 return data().m_public_key_bits;
222 }
223
224 /*
225 * Return the public key of the requestor
226 */
227 Public_Key* PKCS10_Request::subject_public_key() const
228 {
229 DataSource_Memory source(raw_public_key());
230 return X509::load_key(source);
231 }
232
233 /*
234 * Return the alternative names of the requestor
235 */
236 const AlternativeName& PKCS10_Request::subject_alt_name() const
237 {
238 return data().m_alt_name;
239 }
240
241 /*
242 * Return the X509v3 extensions
243 */
244 const Extensions& PKCS10_Request::extensions() const
245 {
246 return data().m_extensions;
247 }
248
249 /*
250 * Return the key constraints (if any)
251 */
252 Key_Constraints PKCS10_Request::constraints() const
253 {
254 if(auto ext = extensions().get(OID::from_string("X509v3.KeyUsage")))
255 {
256 return dynamic_cast<Cert_Extension::Key_Usage&>(*ext).get_constraints();
257 }
258
259 return NO_CONSTRAINTS;
260 }
261
262 /*
263 * Return the extendend key constraints (if any)
264 */
265 std::vector<OID> PKCS10_Request::ex_constraints() const
266 {
267 if(auto ext = extensions().get(OID::from_string("X509v3.ExtendedKeyUsage")))
268 {
269 return dynamic_cast<Cert_Extension::Extended_Key_Usage&>(*ext).get_oids();
270 }
271
272 return {};
273 }
274
275 /*
276 * Return is a CA certificate is requested
277 */
278 bool PKCS10_Request::is_CA() const
279 {
280 if(auto ext = extensions().get(OID::from_string("X509v3.BasicConstraints")))
281 {
282 return dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext).get_is_ca();
283 }
284
285 return false;
286 }
287
288 /*
289 * Return the desired path limit (if any)
290 */
291 size_t PKCS10_Request::path_limit() const
292 {
293 if(auto ext = extensions().get(OID::from_string("X509v3.BasicConstraints")))
294 {
295 Cert_Extension::Basic_Constraints& basic_constraints = dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext);
296 if(basic_constraints.get_is_ca())
297 {
298 return basic_constraints.get_path_limit();
299 }
300 }
301
302 return 0;
303 }
304
305 }
Botan::Cert_Extension::Key_Usage
Definition: x509_ext.h:326
Botan::PKCS10_Request::subject_dn
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:211
Botan::PKCS10_Request::subject_alt_name
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:236
Botan::DataSource_Stream
Definition: data_src.h:143
Botan::X509_Object::signed_body
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:43
Botan::PKCS10_Request::path_limit
size_t path_limit() const
Definition: pkcs10.cpp:291
Botan::Cert_Extension::Extended_Key_Usage::get_oids
const std::vector< OID > & get_oids() const
Definition: x509_ext.h:481
Botan::PKCS10_Request::ex_constraints
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:265
Botan::RandomNumberGenerator
Definition: rng.h:24
Botan::Cert_Extension::Basic_Constraints::get_path_limit
size_t get_path_limit() const
Definition: x509_ext.cpp:317
Botan::BER_Object::length
size_t length() const
Definition: asn1_obj.h:119
Botan::PKCS10_Request::subject_public_key
Public_Key * subject_public_key() const
Definition: pkcs10.cpp:227
Botan::Private_Key
Definition: pk_keys.h:181
Botan::PKCS10_Request::is_CA
bool is_CA() const
Definition: pkcs10.cpp:278
Botan::PKCS10_Request::create
static PKCS10_Request create(const Private_Key &key, const X509_DN &subject_dn, const Extensions &extensions, const std::string &hash_fn, RandomNumberGenerator &rng, const std::string &padding_scheme="", const std::string &challenge="")
Definition: pkcs10.cpp:58
Botan::X509_Object::make_signed
static std::vector< uint8_t > make_signed(class PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &tbs)
Definition: x509_obj.cpp:268
Botan::DER_Encoder::get_contents
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:152
Botan::CONSTRUCTED
Definition: asn1_obj.h:28
Botan::Extensions
Definition: x509_ext.h:90
Botan::PKCS10_Request::extensions
const Extensions & extensions() const
Definition: pkcs10.cpp:244
Botan::DER_Encoder::end_explicit
DER_Encoder & end_explicit()
Definition: der_enc.cpp:220
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::ASN1_Tag
ASN1_Tag
Definition: asn1_obj.h:23
Botan::Cert_Extension::Extended_Key_Usage
Definition: x509_ext.h:472
Botan::DER_Encoder::end_cons
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
Botan::BER_Object::is_a
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const
Definition: asn1_obj.cpp:71
Botan::DataSource
Definition: data_src.h:21
Botan::Cert_Extension::Basic_Constraints
Definition: x509_ext.h:296
Botan::DER_Encoder::raw_bytes
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:228
Botan::ASN1_String
Definition: asn1_str.h:19
Botan::PKCS10_Request::raw_public_key
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:219
Botan::NO_CONSTRAINTS
Definition: key_constraint.h:22
Botan::Cert_Extension::Key_Usage::get_constraints
Key_Constraints get_constraints() const
Definition: x509_ext.h:333
Botan::Decoding_Error
Definition: exceptn.h:199
Botan::BER_Object::bits
const uint8_t * bits() const
Definition: asn1_obj.h:117
Botan::BER_Object::tagging
ASN1_Tag tagging() const
Definition: asn1_obj.h:112
Botan::DER_Encoder::encode
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
Botan::SEQUENCE
Definition: asn1_obj.h:40
Botan::DER_Encoder
Definition: der_enc.h:23
Botan::X509_Object::choose_sig_format
static std::unique_ptr< PK_Signer > choose_sig_format(AlgorithmIdentifier &sig_algo, const Private_Key &key, RandomNumberGenerator &rng, const std::string &hash_fn, const std::string &padding_algo)
Definition: x509_obj.cpp:376
Botan::X509_DN
Definition: x509_dn.h:24
Botan::X509_Object::load_data
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
Botan::PKCS10_Request
Definition: pkcs10.h:28
Botan
Definition: alg_id.cpp:13
Botan::Public_Key
Definition: pk_keys.h:29
Botan::PKCS10_Request::constraints
Key_Constraints constraints() const
Definition: pkcs10.cpp:252
Botan::ASN1::put_in_sequence
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:195
Botan::Attribute::get_oid
const OID & get_oid() const
Definition: asn1_attribute.h:30
Botan::PKCS10_Request::challenge_password
std::string challenge_password() const
Definition: pkcs10.cpp:203
Botan::Attribute::get_parameters
const std::vector< uint8_t > & get_parameters() const
Definition: asn1_attribute.h:32
Botan::X509_Object::check_signature
bool check_signature(const Public_Key &key) const
Definition: x509_obj.cpp:178
Botan::DataSource_Memory
Definition: data_src.h:98
Botan::BER_Bad_Tag
Definition: asn1_obj.h:181
Botan::PKCS10_Request::PKCS10_Request
PKCS10_Request(DataSource &source)
Definition: pkcs10.cpp:38
Botan::AlgorithmIdentifier
Definition: alg_id.h:21
Botan::DER_Encoder::start_cons
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
Botan::PKCS11::Attribute
CK_ATTRIBUTE Attribute
Definition: p11.h:845
Botan::CONTEXT_SPECIFIC
Definition: asn1_obj.h:26
Botan::DIRECTORY_STRING
Definition: asn1_obj.h:57
Botan::ASN1_String::value
const std::string & value() const
Definition: asn1_str.h:27
Botan::OID
Definition: asn1_oid.h:20
Botan::Public_Key::subject_public_key
std::vector< uint8_t > subject_public_key() const
Definition: pk_keys.cpp:38
Botan::BER_Decoder
Definition: ber_dec.h:21
Botan::BER_Object
Definition: asn1_obj.h:97
Botan::Key_Constraints
Key_Constraints
Definition: key_constraint.h:21
Botan::Attribute
Definition: asn1_attribute.h:20
Botan::Cert_Extension::Basic_Constraints::get_is_ca
bool get_is_ca() const
Definition: x509_ext.h:305
Botan::X509::load_key
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37
Botan::AlternativeName
Definition: asn1_alt_name.h:21
Botan::OID::from_string
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:62