/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 | 0 | { |
24 | 0 | switch(code) |
25 | 0 | { |
26 | 0 | case 1: |
27 | 0 | return "RSA"; |
28 | 0 | case 2: |
29 | 0 | return "DSA"; |
30 | 0 | case 64: |
31 | 0 | return "ECDSA"; |
32 | 0 | default: |
33 | 0 | return ""; // DH or something else |
34 | 0 | } |
35 | 0 | } |
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 | | m_names(ca_certs), |
59 | | m_cert_key_types({ "RSA", "ECDSA", "DSA" }) |
60 | 0 | { |
61 | 0 | m_schemes = policy.acceptable_signature_schemes(); |
62 | 0 | hash.update(io.send(*this)); |
63 | 0 | } |
64 | | |
65 | | /** |
66 | | * Deserialize a Certificate Request message |
67 | | */ |
68 | | Certificate_Req::Certificate_Req(const std::vector<uint8_t>& buf) |
69 | 0 | { |
70 | 0 | if(buf.size() < 4) |
71 | 0 | throw Decoding_Error("Certificate_Req: Bad certificate request"); |
72 | | |
73 | 0 | TLS_Data_Reader reader("CertificateRequest", buf); |
74 | |
|
75 | 0 | std::vector<uint8_t> cert_type_codes = reader.get_range_vector<uint8_t>(1, 1, 255); |
76 | |
|
77 | 0 | for(size_t i = 0; i != cert_type_codes.size(); ++i) |
78 | 0 | { |
79 | 0 | const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]); |
80 | |
|
81 | 0 | if(cert_type_name.empty()) // something we don't know |
82 | 0 | continue; |
83 | | |
84 | 0 | m_cert_key_types.emplace_back(cert_type_name); |
85 | 0 | } |
86 | |
|
87 | 0 | const std::vector<uint8_t> algs = reader.get_range_vector<uint8_t>(2, 2, 65534); |
88 | |
|
89 | 0 | if(algs.size() % 2 != 0) |
90 | 0 | throw Decoding_Error("Bad length for signature IDs in certificate request"); |
91 | | |
92 | 0 | for(size_t i = 0; i != algs.size(); i += 2) |
93 | 0 | { |
94 | 0 | m_schemes.push_back(static_cast<Signature_Scheme>(make_uint16(algs[i], algs[i+1]))); |
95 | 0 | } |
96 | |
|
97 | 0 | const uint16_t purported_size = reader.get_uint16_t(); |
98 | |
|
99 | 0 | if(reader.remaining_bytes() != purported_size) |
100 | 0 | throw Decoding_Error("Inconsistent length in certificate request"); |
101 | | |
102 | 0 | while(reader.has_remaining()) |
103 | 0 | { |
104 | 0 | std::vector<uint8_t> name_bits = reader.get_range_vector<uint8_t>(2, 0, 65535); |
105 | |
|
106 | 0 | BER_Decoder decoder(name_bits.data(), name_bits.size()); |
107 | 0 | X509_DN name; |
108 | 0 | decoder.decode(name); |
109 | 0 | m_names.emplace_back(name); |
110 | 0 | } |
111 | 0 | } |
112 | | |
113 | | /** |
114 | | * Serialize a Certificate Request message |
115 | | */ |
116 | | std::vector<uint8_t> Certificate_Req::serialize() const |
117 | 0 | { |
118 | 0 | std::vector<uint8_t> buf; |
119 | |
|
120 | 0 | std::vector<uint8_t> cert_types; |
121 | |
|
122 | 0 | for(size_t i = 0; i != m_cert_key_types.size(); ++i) |
123 | 0 | cert_types.push_back(cert_type_name_to_code(m_cert_key_types[i])); |
124 | |
|
125 | 0 | append_tls_length_value(buf, cert_types, 1); |
126 | |
|
127 | 0 | if(m_schemes.size() > 0) |
128 | 0 | buf += Signature_Algorithms(m_schemes).serialize(Connection_Side::SERVER); |
129 | |
|
130 | 0 | std::vector<uint8_t> encoded_names; |
131 | |
|
132 | 0 | for(size_t i = 0; i != m_names.size(); ++i) |
133 | 0 | { |
134 | 0 | DER_Encoder encoder; |
135 | 0 | encoder.encode(m_names[i]); |
136 | |
|
137 | 0 | append_tls_length_value(encoded_names, encoder.get_contents(), 2); |
138 | 0 | } |
139 | |
|
140 | 0 | append_tls_length_value(buf, encoded_names, 2); |
141 | |
|
142 | 0 | return buf; |
143 | 0 | } |
144 | | |
145 | | } |
146 | | |
147 | | } |