Botan  2.4.0
Crypto and TLS for C++11
msg_cert_req.cpp
Go to the documentation of this file.
1 /*
2 * Certificate Request Message
3 * (C) 2004-2006,2012 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/tls_messages.h>
9 #include <botan/tls_extensions.h>
10 #include <botan/internal/tls_reader.h>
11 #include <botan/internal/tls_handshake_io.h>
12 #include <botan/internal/tls_handshake_hash.h>
13 #include <botan/der_enc.h>
14 #include <botan/ber_dec.h>
15 
16 namespace Botan {
17 
18 namespace TLS {
19 
20 namespace {
21 
22 std::string cert_type_code_to_name(uint8_t code)
23  {
24  switch(code)
25  {
26  case 1:
27  return "RSA";
28  case 2:
29  return "DSA";
30  case 64:
31  return "ECDSA";
32  default:
33  return ""; // DH or something else
34  }
35  }
36 
37 uint8_t cert_type_name_to_code(const std::string& name)
38  {
39  if(name == "RSA")
40  return 1;
41  if(name == "DSA")
42  return 2;
43  if(name == "ECDSA")
44  return 64;
45 
46  throw Invalid_Argument("Unknown cert type " + name);
47  }
48 
49 }
50 
51 /**
52 * Create a new Certificate Request message
53 */
56  const Policy& policy,
57  const std::vector<X509_DN>& ca_certs,
58  Protocol_Version version) :
59  m_names(ca_certs),
60  m_cert_key_types({ "RSA", "DSA", "ECDSA" })
61  {
62  if(version.supports_negotiable_signature_algorithms())
63  {
64  std::vector<std::string> hashes = policy.allowed_signature_hashes();
65  std::vector<std::string> sigs = policy.allowed_signature_methods();
66 
67  for(size_t i = 0; i != hashes.size(); ++i)
68  for(size_t j = 0; j != sigs.size(); ++j)
69  m_supported_algos.push_back(std::make_pair(hashes[i], sigs[j]));
70  }
71 
72  hash.update(io.send(*this));
73  }
74 
75 /**
76 * Deserialize a Certificate Request message
77 */
78 Certificate_Req::Certificate_Req(const std::vector<uint8_t>& buf,
79  Protocol_Version version)
80  {
81  if(buf.size() < 4)
82  throw Decoding_Error("Certificate_Req: Bad certificate request");
83 
84  TLS_Data_Reader reader("CertificateRequest", buf);
85 
86  std::vector<uint8_t> cert_type_codes = reader.get_range_vector<uint8_t>(1, 1, 255);
87 
88  for(size_t i = 0; i != cert_type_codes.size(); ++i)
89  {
90  const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]);
91 
92  if(cert_type_name.empty()) // something we don't know
93  continue;
94 
95  m_cert_key_types.push_back(cert_type_name);
96  }
97 
99  {
100  std::vector<uint8_t> sig_hash_algs = reader.get_range_vector<uint8_t>(2, 2, 65534);
101 
102  if(sig_hash_algs.size() % 2 != 0)
103  throw Decoding_Error("Bad length for signature IDs in certificate request");
104 
105  for(size_t i = 0; i != sig_hash_algs.size(); i += 2)
106  {
107  std::string hash = Signature_Algorithms::hash_algo_name(sig_hash_algs[i]);
108  std::string sig = Signature_Algorithms::sig_algo_name(sig_hash_algs[i+1]);
109  m_supported_algos.push_back(std::make_pair(hash, sig));
110  }
111  }
112 
113  const uint16_t purported_size = reader.get_uint16_t();
114 
115  if(reader.remaining_bytes() != purported_size)
116  throw Decoding_Error("Inconsistent length in certificate request");
117 
118  while(reader.has_remaining())
119  {
120  std::vector<uint8_t> name_bits = reader.get_range_vector<uint8_t>(2, 0, 65535);
121 
122  BER_Decoder decoder(name_bits.data(), name_bits.size());
123  X509_DN name;
124  decoder.decode(name);
125  m_names.push_back(name);
126  }
127  }
128 
129 /**
130 * Serialize a Certificate Request message
131 */
132 std::vector<uint8_t> Certificate_Req::serialize() const
133  {
134  std::vector<uint8_t> buf;
135 
136  std::vector<uint8_t> cert_types;
137 
138  for(size_t i = 0; i != m_cert_key_types.size(); ++i)
139  cert_types.push_back(cert_type_name_to_code(m_cert_key_types[i]));
140 
141  append_tls_length_value(buf, cert_types, 1);
142 
143  if(!m_supported_algos.empty())
144  buf += Signature_Algorithms(m_supported_algos).serialize();
145 
146  std::vector<uint8_t> encoded_names;
147 
148  for(size_t i = 0; i != m_names.size(); ++i)
149  {
150  DER_Encoder encoder;
151  encoder.encode(m_names[i]);
152 
153  append_tls_length_value(encoded_names, encoder.get_contents(), 2);
154  }
155 
156  append_tls_length_value(buf, encoded_names, 2);
157 
158  return buf;
159  }
160 
161 }
162 
163 }
Certificate_Req(Handshake_IO &io, Handshake_Hash &hash, const Policy &policy, const std::vector< X509_DN > &allowed_cas, Protocol_Version version)
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:123
bool supports_negotiable_signature_algorithms() const
Definition: tls_version.cpp:60
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:202
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:105
std::vector< uint8_t > serialize() const override
Definition: alg_id.cpp:13
static std::string sig_algo_name(uint8_t code)
size_t remaining_bytes() const
Definition: tls_reader.h:38
MechanismType hash
static std::string hash_algo_name(uint8_t code)
bool has_remaining() const
Definition: tls_reader.h:40
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition: tls_reader.h:185