Botan  2.7.0
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_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 
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
59  const X509_DN& subject_dn,
60  const Extensions& extensions,
61  const std::string& hash_fn,
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)
79  .start_explicit(0);
80 
81  if(challenge.empty() == false)
82  {
83  ASN1_String challenge_str(challenge, DIRECTORY_STRING);
84 
85  tbs_req.encode(
86  Attribute("PKCS9.ChallengePassword",
87  DER_Encoder().encode(challenge_str).get_contents_unlocked()
88  )
89  );
90  }
91 
92  tbs_req.encode(
93  Attribute("PKCS9.ExtensionRequest",
94  DER_Encoder()
95  .start_cons(SEQUENCE)
97  .end_cons()
98  .get_contents_unlocked()
99  )
100  )
101  .end_explicit()
102  .end_cons();
103 
104  const std::vector<uint8_t> req =
105  X509_Object::make_signed(signer.get(), rng, sig_algo,
106  tbs_req.get_contents());
107 
108  return PKCS10_Request(req);
109  }
110 
111 /*
112 * Decode the CertificateRequestInfo
113 */
114 namespace {
115 
116 std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body)
117  {
118  std::unique_ptr<PKCS10_Data> data(new PKCS10_Data);
119 
120  BER_Decoder cert_req_info(body);
121 
122  size_t version;
123  cert_req_info.decode(version);
124  if(version != 0)
125  throw Decoding_Error("Unknown version code in PKCS #10 request: " +
126  std::to_string(version));
127 
128  cert_req_info.decode(data->m_subject_dn);
129 
130  BER_Object public_key = cert_req_info.get_next_object();
131  if(public_key.is_a(SEQUENCE, CONSTRUCTED) == false)
132  throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", public_key.tagging());
133 
134  data->m_public_key_bits = ASN1::put_in_sequence(public_key.bits(), public_key.length());
135 
136  BER_Object attr_bits = cert_req_info.get_next_object();
137 
138  std::set<std::string> pkcs9_email;
139 
140  if(attr_bits.is_a(0, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)))
141  {
142  BER_Decoder attributes(attr_bits);
143  while(attributes.more_items())
144  {
145  Attribute attr;
146  attributes.decode(attr);
147 
148  const OID& oid = attr.get_oid();
149  BER_Decoder value(attr.get_parameters());
150 
151  if(oid == OIDS::lookup("PKCS9.EmailAddress"))
152  {
153  ASN1_String email;
154  value.decode(email);
155  pkcs9_email.insert(email.value());
156  }
157  else if(oid == OIDS::lookup("PKCS9.ChallengePassword"))
158  {
159  ASN1_String challenge_password;
160  value.decode(challenge_password);
161  data->m_challenge = challenge_password.value();
162  }
163  else if(oid == OIDS::lookup("PKCS9.ExtensionRequest"))
164  {
165  value.decode(data->m_extensions).verify_end();
166  }
167  }
168  attributes.verify_end();
169  }
170  else if(attr_bits.is_set())
171  throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", attr_bits.tagging());
172 
173  cert_req_info.verify_end();
174 
175  if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>())
176  {
177  data->m_alt_name = ext->get_alt_name();
178  }
179 
180  for(std::string email : pkcs9_email)
181  {
182  data->m_alt_name.add_attribute("RFC882", email);
183  }
184 
185  return data;
186  }
187 
188 }
189 
190 void PKCS10_Request::force_decode()
191  {
192  m_data.reset();
193 
194  std::unique_ptr<PKCS10_Data> data = decode_pkcs10(signed_body());
195 
196  m_data.reset(data.release());
197 
198  if(!this->check_signature(subject_public_key()))
199  throw Decoding_Error("PKCS #10 request: Bad signature detected");
200  }
201 
202 const PKCS10_Data& PKCS10_Request::data() const
203  {
204  if(m_data == nullptr)
205  throw Decoding_Error("PKCS10_Request decoding failed");
206  return *m_data.get();
207  }
208 
209 /*
210 * Return the challenge password (if any)
211 */
213  {
214  return data().m_challenge;
215  }
216 
217 /*
218 * Return the name of the requestor
219 */
221  {
222  return data().m_subject_dn;
223  }
224 
225 /*
226 * Return the public key of the requestor
227 */
228 const std::vector<uint8_t>& PKCS10_Request::raw_public_key() const
229  {
230  return data().m_public_key_bits;
231  }
232 
233 /*
234 * Return the public key of the requestor
235 */
237  {
239  return X509::load_key(source);
240  }
241 
242 /*
243 * Return the alternative names of the requestor
244 */
246  {
247  return data().m_alt_name;
248  }
249 
250 /*
251 * Return the X509v3 extensions
252 */
254  {
255  return data().m_extensions;
256  }
257 
258 /*
259 * Return the key constraints (if any)
260 */
262  {
263  if(auto ext = extensions().get(OIDS::lookup("X509v3.KeyUsage")))
264  {
265  return dynamic_cast<Cert_Extension::Key_Usage&>(*ext).get_constraints();
266  }
267 
268  return NO_CONSTRAINTS;
269  }
270 
271 /*
272 * Return the extendend key constraints (if any)
273 */
274 std::vector<OID> PKCS10_Request::ex_constraints() const
275  {
276  if(auto ext = extensions().get(OIDS::lookup("X509v3.ExtendedKeyUsage")))
277  {
278  return dynamic_cast<Cert_Extension::Extended_Key_Usage&>(*ext).get_oids();
279  }
280 
281  return {};
282  }
283 
284 /*
285 * Return is a CA certificate is requested
286 */
288  {
289  if(auto ext = extensions().get(OIDS::lookup("X509v3.BasicConstraints")))
290  {
291  return dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext).get_is_ca();
292  }
293 
294  return false;
295  }
296 
297 /*
298 * Return the desired path limit (if any)
299 */
301  {
302  if(auto ext = extensions().get(OIDS::lookup("X509v3.BasicConstraints")))
303  {
304  Cert_Extension::Basic_Constraints& basic_constraints = dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext);
305  if(basic_constraints.get_is_ca())
306  {
307  return basic_constraints.get_path_limit();
308  }
309  }
310 
311  return 0;
312  }
313 
314 }
ASN1_Tag tagging() const
Definition: asn1_obj.h:113
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:245
Key_Constraints get_constraints() const
Definition: x509_ext.h:324
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:228
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
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:300
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:270
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:210
ASN1_Tag
Definition: asn1_obj.h:22
std::string challenge_password() const
Definition: pkcs10.cpp:212
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:253
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:366
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
bool is_CA() const
Definition: pkcs10.cpp:287
Key_Constraints constraints() const
Definition: pkcs10.cpp:261
const OID & get_oid() const
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:43
void load_data(DataSource &src)
Definition: x509_obj.cpp:53
size_t length() const
Definition: asn1_obj.h:120
Definition: alg_id.cpp:13
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:192
const uint8_t * bits() const
Definition: asn1_obj.h:118
const std::string & value() const
Definition: asn1_str.h:27
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:220
const std::vector< uint8_t > & get_parameters() const
PKCS10_Request(DataSource &source)
Definition: pkcs10.cpp:38
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
CK_ATTRIBUTE Attribute
Definition: p11.h:845
Public_Key * subject_public_key() const
Definition: pkcs10.cpp:236
std::string lookup(const OID &oid)
Definition: oids.cpp:113
const std::vector< OID > & get_oids() const
Definition: x509_ext.h:472
std::vector< uint8_t > subject_public_key() const
Definition: pk_keys.cpp:38
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:274