1 /*
2 * X.509 SIGNED Object
3 * (C) 1999-2007,2020 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/x509_obj.h>
9 #include <botan/pubkey.h>
10 #include <botan/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/parsing.h>
13 #include <botan/pem.h>
14 #include <botan/emsa.h>
15 #include <algorithm>
16
17 namespace Botan {
18
19 namespace {
20 struct Pss_params
21 {
22 AlgorithmIdentifier hash_algo;
23 AlgorithmIdentifier mask_gen_algo;
24 AlgorithmIdentifier mask_gen_hash; // redundant: decoded mask_gen_algo.parameters
25 size_t salt_len;
26 size_t trailer_field;
27 };
28
decode_pss_params(const std::vector<uint8_t> & encoded_pss_params)29 Pss_params decode_pss_params(const std::vector<uint8_t>& encoded_pss_params)
30 {
31 const AlgorithmIdentifier default_hash("SHA-160", AlgorithmIdentifier::USE_NULL_PARAM);
32 const AlgorithmIdentifier default_mgf("MGF1", default_hash.BER_encode());
33
34 Pss_params pss_parameter;
35 BER_Decoder(encoded_pss_params)
36 .start_cons(SEQUENCE)
37 .decode_optional(pss_parameter.hash_algo, ASN1_Tag(0), PRIVATE, default_hash)
38 .decode_optional(pss_parameter.mask_gen_algo, ASN1_Tag(1), PRIVATE, default_mgf)
39 .decode_optional(pss_parameter.salt_len, ASN1_Tag(2), PRIVATE, size_t(20))
40 .decode_optional(pss_parameter.trailer_field, ASN1_Tag(3), PRIVATE, size_t(1))
41 .end_cons();
42
43 BER_Decoder(pss_parameter.mask_gen_algo.get_parameters()).decode(pss_parameter.mask_gen_hash);
44
45 return pss_parameter;
46 }
47 }
48
49 /*
50 * Read a PEM or BER X.509 object
51 */
load_data(DataSource & in)52 void X509_Object::load_data(DataSource& in)
53 {
54 try {
55 if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
56 {
57 BER_Decoder dec(in);
58 decode_from(dec);
59 }
60 else
61 {
62 std::string got_label;
63 DataSource_Memory ber(PEM_Code::decode(in, got_label));
64
65 if(got_label != PEM_label())
66 {
67 bool is_alternate = false;
68 for(std::string alt_label : alternate_PEM_labels())
69 {
70 if(got_label == alt_label)
71 {
72 is_alternate = true;
73 break;
74 }
75 }
76
77 if(!is_alternate)
78 throw Decoding_Error("Unexpected PEM label for " + PEM_label() + " of " + got_label);
79 }
80
81 BER_Decoder dec(ber);
82 decode_from(dec);
83 }
84 }
85 catch(Decoding_Error& e)
86 {
87 throw Decoding_Error(PEM_label() + " decoding", e);
88 }
89 }
90
91
encode_into(DER_Encoder & to) const92 void X509_Object::encode_into(DER_Encoder& to) const
93 {
94 to.start_cons(SEQUENCE)
95 .start_cons(SEQUENCE)
96 .raw_bytes(signed_body())
97 .end_cons()
98 .encode(signature_algorithm())
99 .encode(signature(), BIT_STRING)
100 .end_cons();
101 }
102
103 /*
104 * Read a BER encoded X.509 object
105 */
decode_from(BER_Decoder & from)106 void X509_Object::decode_from(BER_Decoder& from)
107 {
108 from.start_cons(SEQUENCE)
109 .start_cons(SEQUENCE)
110 .raw_bytes(m_tbs_bits)
111 .end_cons()
112 .decode(m_sig_algo)
113 .decode(m_sig, BIT_STRING)
114 .end_cons();
115
116 force_decode();
117 }
118
119 /*
120 * Return a PEM encoded X.509 object
121 */
PEM_encode() const122 std::string X509_Object::PEM_encode() const
123 {
124 return PEM_Code::encode(BER_encode(), PEM_label());
125 }
126
127 /*
128 * Return the TBS data
129 */
tbs_data() const130 std::vector<uint8_t> X509_Object::tbs_data() const
131 {
132 return ASN1::put_in_sequence(m_tbs_bits);
133 }
134
135 /*
136 * Return the hash used in generating the signature
137 */
hash_used_for_signature() const138 std::string X509_Object::hash_used_for_signature() const
139 {
140 const OID& oid = m_sig_algo.get_oid();
141 const std::vector<std::string> sig_info = split_on(oid.to_formatted_string(), '/');
142
143 if(sig_info.size() == 1 && sig_info[0] == "Ed25519")
144 return "SHA-512";
145 else if(sig_info.size() != 2)
146 throw Internal_Error("Invalid name format found for " + oid.to_string());
147
148 if(sig_info[1] == "EMSA4")
149 {
150 const OID hash_oid = decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid();
151 return hash_oid.to_formatted_string();
152 }
153 else
154 {
155 const std::vector<std::string> pad_and_hash =
156 parse_algorithm_name(sig_info[1]);
157
158 if(pad_and_hash.size() != 2)
159 {
160 throw Internal_Error("Invalid name format " + sig_info[1]);
161 }
162
163 return pad_and_hash[1];
164 }
165 }
166
167 /*
168 * Check the signature on an object
169 */
check_signature(const Public_Key * pub_key) const170 bool X509_Object::check_signature(const Public_Key* pub_key) const
171 {
172 if(!pub_key)
173 throw Invalid_Argument("No key provided for " + PEM_label() + " signature check");
174 std::unique_ptr<const Public_Key> key(pub_key);
175 return check_signature(*key);
176 }
177
check_signature(const Public_Key & pub_key) const178 bool X509_Object::check_signature(const Public_Key& pub_key) const
179 {
180 const Certificate_Status_Code code = verify_signature(pub_key);
181 return (code == Certificate_Status_Code::VERIFIED);
182 }
183
verify_signature(const Public_Key & pub_key) const184 Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key) const
185 {
186 const std::vector<std::string> sig_info =
187 split_on(m_sig_algo.get_oid().to_formatted_string(), '/');
188
189 if(sig_info.size() < 1 || sig_info.size() > 2 || sig_info[0] != pub_key.algo_name())
190 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
191
192 const std::string pub_key_algo = sig_info[0];
193 std::string padding;
194 if(sig_info.size() == 2)
195 padding = sig_info[1];
196 else if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
197 padding = "Pure";
198 else
199 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
200
201 const Signature_Format format = pub_key.default_x509_signature_format();
202
203 if(padding == "EMSA4")
204 {
205 // "MUST contain RSASSA-PSS-params"
206 if(signature_algorithm().get_parameters().empty())
207 {
208 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
209 }
210
211 Pss_params pss_parameter = decode_pss_params(signature_algorithm().get_parameters());
212
213 // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
214 const std::string hash_algo = pss_parameter.hash_algo.get_oid().to_formatted_string();
215 if(hash_algo != "SHA-160" &&
216 hash_algo != "SHA-224" &&
217 hash_algo != "SHA-256" &&
218 hash_algo != "SHA-384" &&
219 hash_algo != "SHA-512")
220 {
221 return Certificate_Status_Code::UNTRUSTED_HASH;
222 }
223
224 const std::string mgf_algo = pss_parameter.mask_gen_algo.get_oid().to_formatted_string();
225 if(mgf_algo != "MGF1")
226 {
227 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
228 }
229
230 // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm
231 // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
232 if(pss_parameter.mask_gen_hash.get_oid() != pss_parameter.hash_algo.get_oid())
233 {
234 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
235 }
236
237 if(pss_parameter.trailer_field != 1)
238 {
239 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
240 }
241
242 padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
243 }
244 else
245 {
246 /*
247 * For all other signature types the signature parameters should
248 * be either NULL or empty. In theory there is some distinction between
249 * these but in practice they seem to be used somewhat interchangeably.
250 *
251 * The various RFCs all have prescriptions of what is allowed:
252 * RSA - NULL (RFC 3279)
253 * DSA - empty (RFC 3279)
254 * ECDSA - empty (RFC 3279)
255 * GOST - empty (RFC 4491)
256 * Ed25519 - empty (RFC 8410)
257 * XMSS - empty (draft-vangeest-x509-hash-sigs)
258 *
259 * But in practice we find RSA with empty and ECDSA will NULL all
260 * over the place so it's not really possible to enforce. For Ed25519
261 * and XMSS because they are new we attempt to enforce.
262 */
263 if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
264 {
265 if(!signature_algorithm().parameters_are_empty())
266 {
267 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
268 }
269 }
270 else
271 {
272 if(!signature_algorithm().parameters_are_null_or_empty())
273 {
274 return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
275 }
276 }
277 }
278
279 try
280 {
281 PK_Verifier verifier(pub_key, padding, format);
282 const bool valid = verifier.verify_message(tbs_data(), signature());
283
284 if(valid)
285 return Certificate_Status_Code::VERIFIED;
286 else
287 return Certificate_Status_Code::SIGNATURE_ERROR;
288 }
289 catch(Algorithm_Not_Found&)
290 {
291 return Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN;
292 }
293 catch(...)
294 {
295 // This shouldn't happen, fallback to generic signature error
296 return Certificate_Status_Code::SIGNATURE_ERROR;
297 }
298 }
299
300 /*
301 * Apply the X.509 SIGNED macro
302 */
make_signed(PK_Signer * signer,RandomNumberGenerator & rng,const AlgorithmIdentifier & algo,const secure_vector<uint8_t> & tbs_bits)303 std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
304 RandomNumberGenerator& rng,
305 const AlgorithmIdentifier& algo,
306 const secure_vector<uint8_t>& tbs_bits)
307 {
308 const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng);
309
310 std::vector<uint8_t> output;
311 DER_Encoder(output)
312 .start_cons(SEQUENCE)
313 .raw_bytes(tbs_bits)
314 .encode(algo)
315 .encode(signature, BIT_STRING)
316 .end_cons();
317
318 return output;
319 }
320
321 namespace {
322
choose_sig_algo(AlgorithmIdentifier & sig_algo,const Private_Key & key,const std::string & hash_fn,const std::string & user_specified)323 std::string choose_sig_algo(AlgorithmIdentifier& sig_algo,
324 const Private_Key& key,
325 const std::string& hash_fn,
326 const std::string& user_specified)
327 {
328 const std::string algo_name = key.algo_name();
329 std::string padding;
330
331 // check algo_name and set default
332 if(algo_name == "RSA")
333 {
334 // set to EMSA3 for compatibility reasons, originally it was the only option
335 padding = "EMSA3(" + hash_fn + ")";
336 }
337 else if(algo_name == "DSA" ||
338 algo_name == "ECDSA" ||
339 algo_name == "ECGDSA" ||
340 algo_name == "ECKCDSA" ||
341 algo_name == "GOST-34.10" ||
342 algo_name == "GOST-34.10-2012-256" ||
343 algo_name == "GOST-34.10-2012-512")
344 {
345 padding = "EMSA1(" + hash_fn + ")";
346 }
347 else if(algo_name == "Ed25519")
348 {
349 padding = "Pure";
350 }
351 else if(algo_name == "XMSS")
352 {
353 if(user_specified.empty() == true)
354 {
355 throw Invalid_Argument("XMSS requires padding scheme");
356 }
357 padding = user_specified;
358 sig_algo = AlgorithmIdentifier(OID::from_string("XMSS"), AlgorithmIdentifier::USE_EMPTY_PARAM);
359 return padding;
360 }
361 else
362 {
363 throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
364 }
365
366 if(user_specified.empty() == false)
367 {
368 padding = user_specified;
369 }
370
371 if(padding != "Pure")
372 {
373 // try to construct an EMSA object from the padding options or default
374 std::unique_ptr<EMSA> emsa;
375 try
376 {
377 emsa.reset(get_emsa(padding));
378 }
379 /*
380 * get_emsa will throw if opts contains {"padding",<valid_padding>} but
381 * <valid_padding> does not specify a hash function.
382 * Omitting it is valid since it needs to be identical to hash_fn.
383 * If it still throws, something happened that we cannot repair here,
384 * e.g. the algorithm/padding combination is not supported.
385 */
386 catch(...)
387 {
388 emsa.reset(get_emsa(padding + "(" + hash_fn + ")"));
389 }
390
391 if(!emsa)
392 {
393 throw Invalid_Argument("Could not parse padding scheme " + padding);
394 }
395
396 sig_algo = emsa->config_for_x509(key, hash_fn);
397 return emsa->name();
398 }
399 else
400 {
401 sig_algo = AlgorithmIdentifier(OID::from_string("Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
402 return "Pure";
403 }
404 }
405
406 }
407
408 /*
409 * Choose a signing format for the key
410 */
choose_sig_format(AlgorithmIdentifier & sig_algo,const Private_Key & key,RandomNumberGenerator & rng,const std::string & hash_fn,const std::string & padding_algo)411 std::unique_ptr<PK_Signer> X509_Object::choose_sig_format(AlgorithmIdentifier& sig_algo,
412 const Private_Key& key,
413 RandomNumberGenerator& rng,
414 const std::string& hash_fn,
415 const std::string& padding_algo)
416 {
417 const Signature_Format format = key.default_x509_signature_format();
418
419 const std::string emsa = choose_sig_algo(sig_algo, key, hash_fn, padding_algo);
420
421 return std::unique_ptr<PK_Signer>(new PK_Signer(key, rng, emsa, format));
422 }
423
424 }
425