/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 | 7.38k | { |
24 | 7.38k | switch(code) |
25 | 7.38k | { |
26 | 479 | case 1: |
27 | 479 | return "RSA"; |
28 | 798 | case 2: |
29 | 798 | return "DSA"; |
30 | 449 | case 64: |
31 | 449 | return "ECDSA"; |
32 | 5.66k | default: |
33 | 5.66k | return ""; // DH or something else |
34 | 7.38k | } |
35 | 7.38k | } |
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 | | |
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.acceptable_signature_schemes(); |
65 | 0 | } |
66 | |
|
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 | 129 | { |
76 | 129 | if(buf.size() < 4) |
77 | 1 | throw Decoding_Error("Certificate_Req: Bad certificate request"); |
78 | | |
79 | 128 | TLS_Data_Reader reader("CertificateRequest", buf); |
80 | | |
81 | 128 | std::vector<uint8_t> cert_type_codes = reader.get_range_vector<uint8_t>(1, 1, 255); |
82 | | |
83 | 7.51k | for(size_t i = 0; i != cert_type_codes.size(); ++i) |
84 | 7.38k | { |
85 | 7.38k | const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]); |
86 | | |
87 | 7.38k | if(cert_type_name.empty()) // something we don't know |
88 | 5.66k | continue; |
89 | | |
90 | 1.72k | m_cert_key_types.emplace_back(cert_type_name); |
91 | 1.72k | } |
92 | | |
93 | 128 | if(version.supports_negotiable_signature_algorithms()) |
94 | 127 | { |
95 | 127 | const std::vector<uint8_t> algs = reader.get_range_vector<uint8_t>(2, 2, 65534); |
96 | | |
97 | 127 | if(algs.size() % 2 != 0) |
98 | 3 | throw Decoding_Error("Bad length for signature IDs in certificate request"); |
99 | | |
100 | 4.86k | for(size_t i = 0; i != algs.size(); i += 2) |
101 | 4.74k | { |
102 | 4.74k | m_schemes.push_back(static_cast<Signature_Scheme>(make_uint16(algs[i], algs[i+1]))); |
103 | 4.74k | } |
104 | 124 | } |
105 | | |
106 | 125 | const uint16_t purported_size = reader.get_uint16_t(); |
107 | | |
108 | 125 | if(reader.remaining_bytes() != purported_size) |
109 | 31 | throw Decoding_Error("Inconsistent length in certificate request"); |
110 | | |
111 | 8.12k | while(reader.has_remaining()) |
112 | 8.02k | { |
113 | 8.02k | std::vector<uint8_t> name_bits = reader.get_range_vector<uint8_t>(2, 0, 65535); |
114 | | |
115 | 8.02k | BER_Decoder decoder(name_bits.data(), name_bits.size()); |
116 | 8.02k | X509_DN name; |
117 | 8.02k | decoder.decode(name); |
118 | 8.02k | m_names.emplace_back(name); |
119 | 8.02k | } |
120 | 94 | } |
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 | |
|
129 | 0 | std::vector<uint8_t> cert_types; |
130 | |
|
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 | |
|
134 | 0 | append_tls_length_value(buf, cert_types, 1); |
135 | |
|
136 | 0 | if(m_schemes.size() > 0) |
137 | 0 | buf += Signature_Algorithms(m_schemes).serialize(Connection_Side::SERVER); |
138 | |
|
139 | 0 | std::vector<uint8_t> encoded_names; |
140 | |
|
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 | |
|
146 | 0 | append_tls_length_value(encoded_names, encoder.get_contents(), 2); |
147 | 0 | } |
148 | |
|
149 | 0 | append_tls_length_value(buf, encoded_names, 2); |
150 | |
|
151 | 0 | return buf; |
152 | 0 | } |
153 | | |
154 | | } |
155 | | |
156 | | } |