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