Botan  2.4.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/oids.h>
13 #include <botan/pem.h>
14 
15 namespace Botan {
16 
17 struct PKCS10_Data
18  {
19  X509_DN m_subject_dn;
20  std::vector<uint8_t> m_public_key_bits;
21  AlternativeName m_alt_name;
22  std::string m_challenge;
23  Extensions m_extensions;
24  };
25 
26 std::string PKCS10_Request::PEM_label() const
27  {
28  return "CERTIFICATE REQUEST";
29  }
30 
31 std::vector<std::string> PKCS10_Request::alternate_PEM_labels() const
32  {
33  return { "NEW CERTIFICATE REQUEST" };
34  }
35 
37  {
38  load_data(src);
39  }
40 
41 PKCS10_Request::PKCS10_Request(const std::vector<uint8_t>& vec)
42  {
43  DataSource_Memory src(vec.data(), vec.size());
44  load_data(src);
45  }
46 
47 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
48 PKCS10_Request::PKCS10_Request(const std::string& fsname)
49  {
50  DataSource_Stream src(fsname, true);
51  load_data(src);
52  }
53 #endif
54 
55 /*
56 * Decode the CertificateRequestInfo
57 */
58 namespace {
59 
60 std::unique_ptr<PKCS10_Data> decode_pkcs10(const std::vector<uint8_t>& body)
61  {
62  std::unique_ptr<PKCS10_Data> data(new PKCS10_Data);
63 
64  BER_Decoder cert_req_info(body);
65 
66  size_t version;
67  cert_req_info.decode(version);
68  if(version != 0)
69  throw Decoding_Error("Unknown version code in PKCS #10 request: " +
70  std::to_string(version));
71 
72  cert_req_info.decode(data->m_subject_dn);
73 
74  BER_Object public_key = cert_req_info.get_next_object();
75  if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
76  throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key",
77  public_key.type_tag, public_key.class_tag);
78 
79  data->m_public_key_bits = ASN1::put_in_sequence(unlock(public_key.value));
80 
81  BER_Object attr_bits = cert_req_info.get_next_object();
82 
83  std::set<std::string> pkcs9_email;
84 
85  if(attr_bits.type_tag == 0 &&
87  {
88  BER_Decoder attributes(attr_bits.value);
89  while(attributes.more_items())
90  {
91  Attribute attr;
92  attributes.decode(attr);
93 
94  const OID& oid = attr.get_oid();
95  BER_Decoder value(attr.get_parameters());
96 
97  if(oid == OIDS::lookup("PKCS9.EmailAddress"))
98  {
99  ASN1_String email;
100  value.decode(email);
101  pkcs9_email.insert(email.value());
102  }
103  else if(oid == OIDS::lookup("PKCS9.ChallengePassword"))
104  {
105  ASN1_String challenge_password;
106  value.decode(challenge_password);
107  data->m_challenge = challenge_password.value();
108  }
109  else if(oid == OIDS::lookup("PKCS9.ExtensionRequest"))
110  {
111  value.decode(data->m_extensions).verify_end();
112  }
113  }
114  attributes.verify_end();
115  }
116  else if(attr_bits.type_tag != NO_OBJECT)
117  throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes",
118  attr_bits.type_tag, attr_bits.class_tag);
119 
120  cert_req_info.verify_end();
121 
122  if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>())
123  {
124  data->m_alt_name = ext->get_alt_name();
125  }
126 
127  for(std::string email : pkcs9_email)
128  {
129  data->m_alt_name.add_attribute("RFC882", email);
130  }
131 
132  return data;
133  }
134 
135 }
136 
137 void PKCS10_Request::force_decode()
138  {
139  m_data.reset();
140 
141  std::unique_ptr<PKCS10_Data> data = decode_pkcs10(signed_body());
142 
143  m_data.reset(data.release());
144 
145  if(!this->check_signature(subject_public_key()))
146  throw Decoding_Error("PKCS #10 request: Bad signature detected");
147  }
148 
149 const PKCS10_Data& PKCS10_Request::data() const
150  {
151  if(m_data == nullptr)
152  throw Decoding_Error("PKCS10_Request decoding failed");
153  return *m_data.get();
154  }
155 
156 /*
157 * Return the challenge password (if any)
158 */
160  {
161  return data().m_challenge;
162  }
163 
164 /*
165 * Return the name of the requestor
166 */
168  {
169  return data().m_subject_dn;
170  }
171 
172 /*
173 * Return the public key of the requestor
174 */
175 const std::vector<uint8_t>& PKCS10_Request::raw_public_key() const
176  {
177  return data().m_public_key_bits;
178  }
179 
180 /*
181 * Return the public key of the requestor
182 */
184  {
185  DataSource_Memory source(raw_public_key());
186  return X509::load_key(source);
187  }
188 
189 /*
190 * Return the alternative names of the requestor
191 */
193  {
194  return data().m_alt_name;
195  }
196 
197 /*
198 * Return the X509v3 extensions
199 */
201  {
202  return data().m_extensions;
203  }
204 
205 /*
206 * Return the key constraints (if any)
207 */
209  {
210  if(auto ext = extensions().get(OIDS::lookup("X509v3.KeyUsage")))
211  {
212  return dynamic_cast<Cert_Extension::Key_Usage&>(*ext).get_constraints();
213  }
214 
215  return NO_CONSTRAINTS;
216  }
217 
218 /*
219 * Return the extendend key constraints (if any)
220 */
221 std::vector<OID> PKCS10_Request::ex_constraints() const
222  {
223  if(auto ext = extensions().get(OIDS::lookup("X509v3.ExtendedKeyUsage")))
224  {
225  return dynamic_cast<Cert_Extension::Extended_Key_Usage&>(*ext).get_oids();
226  }
227 
228  return {};
229  }
230 
231 /*
232 * Return is a CA certificate is requested
233 */
235  {
236  if(auto ext = extensions().get(OIDS::lookup("X509v3.BasicConstraints")))
237  {
238  return dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext).get_is_ca();
239  }
240 
241  return false;
242  }
243 
244 /*
245 * Return the desired path limit (if any)
246 */
248  {
249  if(auto ext = extensions().get(OIDS::lookup("X509v3.BasicConstraints")))
250  {
251  Cert_Extension::Basic_Constraints& basic_constraints = dynamic_cast<Cert_Extension::Basic_Constraints&>(*ext);
252  if(basic_constraints.get_is_ca())
253  {
254  return basic_constraints.get_path_limit();
255  }
256  }
257 
258  return 0;
259  }
260 
261 }
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:192
Key_Constraints get_constraints() const
Definition: x509_ext.h:314
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:175
size_t path_limit() const
Definition: pkcs10.cpp:247
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:355
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:108
ASN1_Tag
Definition: asn1_obj.h:22
std::string challenge_password() const
Definition: pkcs10.cpp:159
const Extensions & extensions() const
Definition: pkcs10.cpp:200
secure_vector< uint8_t > value
Definition: asn1_obj.h:97
bool is_CA() const
Definition: pkcs10.cpp:234
Key_Constraints constraints() const
Definition: pkcs10.cpp:208
const OID & get_oid() const
Definition: alg_id.cpp:13
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:96
BER_Object get_next_object()
Definition: ber_dec.cpp:197
const std::string & value() const
Definition: asn1_str.h:27
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:95
ASN1_Tag class_tag
Definition: asn1_obj.h:94
ASN1_Tag type_tag
Definition: asn1_obj.h:94
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:167
BER_Decoder & verify_end()
Definition: ber_dec.cpp:176
const std::vector< uint8_t > & get_parameters() const
PKCS10_Request(DataSource &source)
Definition: pkcs10.cpp:36
Public_Key * subject_public_key() const
Definition: pkcs10.cpp:183
bool more_items() const
Definition: ber_dec.cpp:166
std::string lookup(const OID &oid)
Definition: oids.cpp:18
const std::vector< OID > & get_oids() const
Definition: x509_ext.h:461
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:221