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 
PEM_label() const29 std::string PKCS10_Request::PEM_label() const
30    {
31    return "CERTIFICATE REQUEST";
32    }
33 
alternate_PEM_labels() const34 std::vector<std::string> PKCS10_Request::alternate_PEM_labels() const
35    {
36    return { "NEW CERTIFICATE REQUEST" };
37    }
38 
PKCS10_Request(DataSource & src)39 PKCS10_Request::PKCS10_Request(DataSource& src)
40    {
41    load_data(src);
42    }
43 
PKCS10_Request(const std::vector<uint8_t> & vec)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)
PKCS10_Request(const std::string & fsname)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
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)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 
decode_pkcs10(const std::vector<uint8_t> & body)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 
force_decode()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 
data() const192 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 */
challenge_password() const202 std::string PKCS10_Request::challenge_password() const
203    {
204    return data().m_challenge;
205    }
206 
207 /*
208 * Return the name of the requestor
209 */
subject_dn() const210 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 */
raw_public_key() const218 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 */
subject_public_key() const226 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 */
subject_alt_name() const235 const AlternativeName& PKCS10_Request::subject_alt_name() const
236    {
237    return data().m_alt_name;
238    }
239 
240 /*
241 * Return the X509v3 extensions
242 */
extensions() const243 const Extensions& PKCS10_Request::extensions() const
244    {
245    return data().m_extensions;
246    }
247 
248 /*
249 * Return the key constraints (if any)
250 */
constraints() const251 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 */
ex_constraints() const264 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 */
is_CA() const277 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 */
path_limit() const290 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 }
305