Botan  2.18.1
Crypto and TLS for C++11
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 
29 std::string PKCS10_Request::PEM_label() const
30  {
31  return "CERTIFICATE REQUEST";
32  }
33 
34 std::vector<std::string> PKCS10_Request::alternate_PEM_labels() const
35  {
36  return { "NEW CERTIFICATE REQUEST" };
37  }
38 
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
60  const X509_DN& subject_dn,
61  const Extensions& extensions,
62  const std::string& hash_fn,
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)
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;
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 
106 std::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 */
203  {
204  return data().m_challenge;
205  }
206 
207 /*
208 * Return the name of the requestor
209 */
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 */
227  {
229  return X509::load_key(source);
230  }
231 
232 /*
233 * Return the alternative names of the requestor
234 */
236  {
237  return data().m_alt_name;
238  }
239 
240 /*
241 * Return the X509v3 extensions
242 */
244  {
245  return data().m_extensions;
246  }
247 
248 /*
249 * Return the key constraints (if any)
250 */
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 */
264 std::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 */
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 */
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 }
ASN1_Tag tagging() const
Definition: asn1_obj.h:114
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:235
Key_Constraints get_constraints() const
Definition: x509_ext.h:63
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:218
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
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const
Definition: asn1_obj.cpp:71
size_t path_limit() const
Definition: pkcs10.cpp:290
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
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:152
DER_Encoder & end_explicit()
Definition: der_enc.cpp:220
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
ASN1_Tag
Definition: asn1_obj.h:25
std::string challenge_password() const
Definition: pkcs10.cpp:202
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
bool check_signature(const Public_Key &key) const
Definition: x509_obj.cpp:178
const Extensions & extensions() const
Definition: pkcs10.cpp:243
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:228
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
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
bool is_CA() const
Definition: pkcs10.cpp:277
Key_Constraints constraints() const
Definition: pkcs10.cpp:251
const OID & get_oid() const
Definition: pkix_types.h:175
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:42
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
size_t length() const
Definition: asn1_obj.h:121
Definition: alg_id.cpp:13
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:195
const uint8_t * bits() const
Definition: asn1_obj.h:119
const std::string & value() const
Definition: asn1_obj.h:400
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:210
const std::vector< uint8_t > & get_parameters() const
Definition: pkix_types.h:177
PKCS10_Request(DataSource &source)
Definition: pkcs10.cpp:39
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
CK_ATTRIBUTE Attribute
Definition: p11.h:847
Public_Key * subject_public_key() const
Definition: pkcs10.cpp:226
Key_Constraints
Definition: pkix_enums.h:106
const std::vector< OID > & get_oids() const
Definition: x509_ext.h:211
std::vector< uint8_t > subject_public_key() const
Definition: pk_keys.cpp:38
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:62
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:264