Botan  2.4.0
Crypto and TLS for C++11
x509_obj.cpp
Go to the documentation of this file.
1 /*
2 * X.509 SIGNED Object
3 * (C) 1999-2007 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/oids.h>
11 #include <botan/der_enc.h>
12 #include <botan/ber_dec.h>
13 #include <botan/parsing.h>
14 #include <botan/pem.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 
29 Pss_params decode_pss_params(const std::vector<uint8_t>& encoded_pss_params)
30  {
31  Pss_params pss_parameter;
32  BER_Decoder(encoded_pss_params)
33  .start_cons(SEQUENCE)
34  .decode_optional(pss_parameter.hash_algo, ASN1_Tag(0), PRIVATE, AlgorithmIdentifier("SHA-160",
36  .decode_optional(pss_parameter.mask_gen_algo, ASN1_Tag(1), PRIVATE,
37  AlgorithmIdentifier("MGF1", DER_Encoder().encode(AlgorithmIdentifier("SHA-160",
38  AlgorithmIdentifier::USE_NULL_PARAM)).get_contents_unlocked()))
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 */
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 failed: " + e.what());
88  }
89  }
90 
91 
93  {
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 */
107  {
108  from.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 BER encoded X.509 object
121 */
122 std::vector<uint8_t> X509_Object::BER_encode() const
123  {
124  DER_Encoder der;
125  encode_into(der);
126  return der.get_contents_unlocked();
127  }
128 
129 /*
130 * Return a PEM encoded X.509 object
131 */
132 std::string X509_Object::PEM_encode() const
133  {
134  return PEM_Code::encode(BER_encode(), PEM_label());
135  }
136 
137 /*
138 * Return the TBS data
139 */
140 std::vector<uint8_t> X509_Object::tbs_data() const
141  {
142  return ASN1::put_in_sequence(m_tbs_bits);
143  }
144 
145 /*
146 * Return the hash used in generating the signature
147 */
149  {
150  const OID& oid = m_sig_algo.get_oid();
151  std::vector<std::string> sig_info = split_on(OIDS::lookup(oid), '/');
152 
153  if(sig_info.size() != 2)
154  throw Internal_Error("Invalid name format found for " +
155  oid.as_string());
156 
157  if(sig_info[1] == "EMSA4")
158  {
159  return OIDS::lookup(decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid());
160  }
161  else
162  {
163  std::vector<std::string> pad_and_hash =
164  parse_algorithm_name(sig_info[1]);
165 
166  if(pad_and_hash.size() != 2)
167  {
168  throw Internal_Error("Invalid name format " + sig_info[1]);
169  }
170 
171  return pad_and_hash[1];
172  }
173  }
174 
175 /*
176 * Check the signature on an object
177 */
178 bool X509_Object::check_signature(const Public_Key* pub_key) const
179  {
180  if(!pub_key)
181  throw Exception("No key provided for " + PEM_label() + " signature check");
182  std::unique_ptr<const Public_Key> key(pub_key);
183  return check_signature(*key);
184  }
185 
186 bool X509_Object::check_signature(const Public_Key& pub_key) const
187  {
188  const Certificate_Status_Code code = verify_signature(pub_key);
189  return (code == Certificate_Status_Code::VERIFIED);
190  }
191 
193  {
194  const std::vector<std::string> sig_info =
195  split_on(OIDS::lookup(m_sig_algo.get_oid()), '/');
196 
197  if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
199 
200  std::string padding = sig_info[1];
201  const Signature_Format format =
202  (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
203 
204  if(padding == "EMSA4")
205  {
206  // "MUST contain RSASSA-PSS-params"
207  if(signature_algorithm().parameters.empty())
208  {
210  }
211 
212  Pss_params pss_parameter = decode_pss_params(signature_algorithm().parameters);
213 
214  // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
215  const std::string hash_algo = OIDS::lookup(pss_parameter.hash_algo.oid);
216  if(hash_algo != "SHA-160" &&
217  hash_algo != "SHA-224" &&
218  hash_algo != "SHA-256" &&
219  hash_algo != "SHA-384" &&
220  hash_algo != "SHA-512")
221  {
223  }
224 
225  const std::string mgf_algo = OIDS::lookup(pss_parameter.mask_gen_algo.oid);
226  if(mgf_algo != "MGF1")
227  {
229  }
230 
231  // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm
232  // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
233  if(pss_parameter.mask_gen_hash.oid != pss_parameter.hash_algo.oid)
234  {
236  }
237 
238  if(pss_parameter.trailer_field != 1)
239  {
241  }
242 
243  // salt_len is actually not used for verification. Length is inferred from the signature
244  padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
245  }
246 
247  try
248  {
249  PK_Verifier verifier(pub_key, padding, format);
250  const bool valid = verifier.verify_message(tbs_data(), signature());
251 
252  if(valid)
254  else
256  }
257  catch(Algorithm_Not_Found&)
258  {
260  }
261  catch(...)
262  {
263  // This shouldn't happen, fallback to generic signature error
265  }
266  }
267 
268 /*
269 * Apply the X.509 SIGNED macro
270 */
271 std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
273  const AlgorithmIdentifier& algo,
274  const secure_vector<uint8_t>& tbs_bits)
275  {
276  const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng);
277 
278  return DER_Encoder()
280  .raw_bytes(tbs_bits)
281  .encode(algo)
282  .encode(signature, BIT_STRING)
283  .end_cons()
285  }
286 
287 }
Certificate_Status_Code verify_signature(const Public_Key &key) const
Definition: x509_obj.cpp:192
std::vector< uint8_t > get_contents_unlocked()
Definition: der_enc.h:27
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition: pubkey.cpp:281
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:142
void encode_into(class DER_Encoder &to) const override
Definition: x509_obj.cpp:92
std::string as_string() const
Definition: asn1_oid.cpp:50
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:271
AlgorithmIdentifier mask_gen_hash
Definition: x509_obj.cpp:24
Signature_Format
Definition: pubkey.h:27
AlgorithmIdentifier mask_gen_algo
Definition: x509_obj.cpp:23
virtual std::string algo_name() const =0
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:355
bool maybe_BER(DataSource &source)
Definition: asn1_obj.cpp:116
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:108
ASN1_Tag
Definition: asn1_obj.h:22
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition: ber_dec.h:73
DER_Encoder & end_cons()
Definition: der_enc.cpp:146
bool check_signature(const Public_Key &key) const
Definition: x509_obj.cpp:186
std::vector< uint8_t > sign_message(const uint8_t in[], size_t length, RandomNumberGenerator &rng)
Definition: pubkey.h:207
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:181
void decode_from(class BER_Decoder &from) override
Definition: x509_obj.cpp:106
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:202
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
BER_Decoder & end_cons()
Definition: ber_dec.cpp:265
bool matches(DataSource &source, const std::string &extra, size_t search_range)
Definition: pem.cpp:142
std::vector< uint8_t > tbs_data() const
Definition: x509_obj.cpp:140
const char * what() const BOTAN_NOEXCEPT override
Definition: exceptn.h:25
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
size_t salt_len
Definition: x509_obj.cpp:25
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:251
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:89
Definition: alg_id.cpp:13
secure_vector< uint8_t > BER_encode(const Private_Key &key)
Definition: pkcs8.cpp:131
AlgorithmIdentifier hash_algo
Definition: x509_obj.cpp:22
std::vector< uint8_t > BER_encode() const
Definition: x509_obj.cpp:122
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:96
size_t trailer_field
Definition: x509_obj.cpp:26
std::string hash_used_for_signature() const
Definition: x509_obj.cpp:148
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:136
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
Certificate_Status_Code
Definition: cert_status.h:18
std::string lookup(const OID &oid)
Definition: oids.cpp:18
std::string PEM_encode() const
Definition: x509_obj.cpp:132
virtual size_t message_parts() const
Definition: pk_keys.h:107