/src/botan/src/lib/tls/msg_cert_req.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 9.18k | { |
24 | 9.18k | switch(code) |
25 | 9.18k | { |
26 | 1.83k | case 1: |
27 | 1.83k | return "RSA"; |
28 | 2.72k | case 2: |
29 | 2.72k | return "DSA"; |
30 | 947 | case 64: |
31 | 947 | return "ECDSA"; |
32 | 3.67k | default: |
33 | 3.67k | return ""; // DH or something else |
34 | 9.18k | } |
35 | 9.18k | } |
36 | | |
37 | | uint8_t cert_type_name_to_code(const std::string& name) |
38 | 0 | { |
39 | 0 | if(name == "RSA") |
40 | 0 | return 1; |
41 | 0 | if(name == "DSA") |
42 | 0 | return 2; |
43 | 0 | if(name == "ECDSA") |
44 | 0 | return 64; |
45 | 0 | |
46 | 0 | throw Invalid_Argument("Unknown cert type " + name); |
47 | 0 | } |
48 | | |
49 | | } |
50 | | |
51 | | /** |
52 | | * Create a new Certificate Request message |
53 | | */ |
54 | | Certificate_Req::Certificate_Req(Handshake_IO& io, |
55 | | Handshake_Hash& hash, |
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", "ECDSA", "DSA" }) |
61 | 0 | { |
62 | 0 | if(version.supports_negotiable_signature_algorithms()) |
63 | 0 | { |
64 | 0 | m_schemes = policy.allowed_signature_schemes(); |
65 | 0 | } |
66 | 0 |
|
67 | 0 | hash.update(io.send(*this)); |
68 | 0 | } |
69 | | |
70 | | /** |
71 | | * Deserialize a Certificate Request message |
72 | | */ |
73 | | Certificate_Req::Certificate_Req(const std::vector<uint8_t>& buf, |
74 | | Protocol_Version version) |
75 | 164 | { |
76 | 164 | if(buf.size() < 4) |
77 | 4 | throw Decoding_Error("Certificate_Req: Bad certificate request"); |
78 | 160 | |
79 | 160 | TLS_Data_Reader reader("CertificateRequest", buf); |
80 | 160 | |
81 | 160 | std::vector<uint8_t> cert_type_codes = reader.get_range_vector<uint8_t>(1, 1, 255); |
82 | 160 | |
83 | 9.34k | for(size_t i = 0; i != cert_type_codes.size(); ++i) |
84 | 9.18k | { |
85 | 9.18k | const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]); |
86 | 9.18k | |
87 | 9.18k | if(cert_type_name.empty()) // something we don't know |
88 | 3.67k | continue; |
89 | 5.50k | |
90 | 5.50k | m_cert_key_types.emplace_back(cert_type_name); |
91 | 5.50k | } |
92 | 160 | |
93 | 160 | if(version.supports_negotiable_signature_algorithms()) |
94 | 158 | { |
95 | 158 | const std::vector<uint8_t> algs = reader.get_range_vector<uint8_t>(2, 2, 65534); |
96 | 158 | |
97 | 158 | if(algs.size() % 2 != 0) |
98 | 2 | throw Decoding_Error("Bad length for signature IDs in certificate request"); |
99 | 156 | |
100 | 3.80k | for(size_t i = 0; i != algs.size(); i += 2) |
101 | 3.65k | { |
102 | 3.65k | m_schemes.push_back(static_cast<Signature_Scheme>(make_uint16(algs[i], algs[i+1]))); |
103 | 3.65k | } |
104 | 156 | } |
105 | 160 | |
106 | 158 | const uint16_t purported_size = reader.get_uint16_t(); |
107 | 158 | |
108 | 158 | if(reader.remaining_bytes() != purported_size) |
109 | 45 | throw Decoding_Error("Inconsistent length in certificate request"); |
110 | 113 | |
111 | 644 | while(reader.has_remaining()) |
112 | 531 | { |
113 | 531 | std::vector<uint8_t> name_bits = reader.get_range_vector<uint8_t>(2, 0, 65535); |
114 | 531 | |
115 | 531 | BER_Decoder decoder(name_bits.data(), name_bits.size()); |
116 | 531 | X509_DN name; |
117 | 531 | decoder.decode(name); |
118 | 531 | m_names.emplace_back(name); |
119 | 531 | } |
120 | 113 | } |
121 | | |
122 | | /** |
123 | | * Serialize a Certificate Request message |
124 | | */ |
125 | | std::vector<uint8_t> Certificate_Req::serialize() const |
126 | 0 | { |
127 | 0 | std::vector<uint8_t> buf; |
128 | 0 |
|
129 | 0 | std::vector<uint8_t> cert_types; |
130 | 0 |
|
131 | 0 | for(size_t i = 0; i != m_cert_key_types.size(); ++i) |
132 | 0 | cert_types.push_back(cert_type_name_to_code(m_cert_key_types[i])); |
133 | 0 |
|
134 | 0 | append_tls_length_value(buf, cert_types, 1); |
135 | 0 |
|
136 | 0 | if(m_schemes.size() > 0) |
137 | 0 | buf += Signature_Algorithms(m_schemes).serialize(Connection_Side::SERVER); |
138 | 0 |
|
139 | 0 | std::vector<uint8_t> encoded_names; |
140 | 0 |
|
141 | 0 | for(size_t i = 0; i != m_names.size(); ++i) |
142 | 0 | { |
143 | 0 | DER_Encoder encoder; |
144 | 0 | encoder.encode(m_names[i]); |
145 | 0 |
|
146 | 0 | append_tls_length_value(encoded_names, encoder.get_contents(), 2); |
147 | 0 | } |
148 | 0 |
|
149 | 0 | append_tls_length_value(buf, encoded_names, 2); |
150 | 0 |
|
151 | 0 | return buf; |
152 | 0 | } |
153 | | |
154 | | } |
155 | | |
156 | | } |