summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/tls/msg_cert_req.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/tls/msg_cert_req.cpp')
-rw-r--r--comm/third_party/botan/src/lib/tls/msg_cert_req.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/tls/msg_cert_req.cpp b/comm/third_party/botan/src/lib/tls/msg_cert_req.cpp
new file mode 100644
index 0000000000..9e8a4d803c
--- /dev/null
+++ b/comm/third_party/botan/src/lib/tls/msg_cert_req.cpp
@@ -0,0 +1,156 @@
+/*
+* Certificate Request Message
+* (C) 2004-2006,2012 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/tls_messages.h>
+#include <botan/tls_extensions.h>
+#include <botan/internal/tls_reader.h>
+#include <botan/internal/tls_handshake_io.h>
+#include <botan/internal/tls_handshake_hash.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+
+namespace Botan {
+
+namespace TLS {
+
+namespace {
+
+std::string cert_type_code_to_name(uint8_t code)
+ {
+ switch(code)
+ {
+ case 1:
+ return "RSA";
+ case 2:
+ return "DSA";
+ case 64:
+ return "ECDSA";
+ default:
+ return ""; // DH or something else
+ }
+ }
+
+uint8_t cert_type_name_to_code(const std::string& name)
+ {
+ if(name == "RSA")
+ return 1;
+ if(name == "DSA")
+ return 2;
+ if(name == "ECDSA")
+ return 64;
+
+ throw Invalid_Argument("Unknown cert type " + name);
+ }
+
+}
+
+/**
+* Create a new Certificate Request message
+*/
+Certificate_Req::Certificate_Req(Handshake_IO& io,
+ Handshake_Hash& hash,
+ const Policy& policy,
+ const std::vector<X509_DN>& ca_certs,
+ Protocol_Version version) :
+ m_names(ca_certs),
+ m_cert_key_types({ "RSA", "ECDSA", "DSA" })
+ {
+ if(version.supports_negotiable_signature_algorithms())
+ {
+ m_schemes = policy.allowed_signature_schemes();
+ }
+
+ hash.update(io.send(*this));
+ }
+
+/**
+* Deserialize a Certificate Request message
+*/
+Certificate_Req::Certificate_Req(const std::vector<uint8_t>& buf,
+ Protocol_Version version)
+ {
+ if(buf.size() < 4)
+ throw Decoding_Error("Certificate_Req: Bad certificate request");
+
+ TLS_Data_Reader reader("CertificateRequest", buf);
+
+ std::vector<uint8_t> cert_type_codes = reader.get_range_vector<uint8_t>(1, 1, 255);
+
+ for(size_t i = 0; i != cert_type_codes.size(); ++i)
+ {
+ const std::string cert_type_name = cert_type_code_to_name(cert_type_codes[i]);
+
+ if(cert_type_name.empty()) // something we don't know
+ continue;
+
+ m_cert_key_types.emplace_back(cert_type_name);
+ }
+
+ if(version.supports_negotiable_signature_algorithms())
+ {
+ const std::vector<uint8_t> algs = reader.get_range_vector<uint8_t>(2, 2, 65534);
+
+ if(algs.size() % 2 != 0)
+ throw Decoding_Error("Bad length for signature IDs in certificate request");
+
+ for(size_t i = 0; i != algs.size(); i += 2)
+ {
+ m_schemes.push_back(static_cast<Signature_Scheme>(make_uint16(algs[i], algs[i+1])));
+ }
+ }
+
+ const uint16_t purported_size = reader.get_uint16_t();
+
+ if(reader.remaining_bytes() != purported_size)
+ throw Decoding_Error("Inconsistent length in certificate request");
+
+ while(reader.has_remaining())
+ {
+ std::vector<uint8_t> name_bits = reader.get_range_vector<uint8_t>(2, 0, 65535);
+
+ BER_Decoder decoder(name_bits.data(), name_bits.size());
+ X509_DN name;
+ decoder.decode(name);
+ m_names.emplace_back(name);
+ }
+ }
+
+/**
+* Serialize a Certificate Request message
+*/
+std::vector<uint8_t> Certificate_Req::serialize() const
+ {
+ std::vector<uint8_t> buf;
+
+ std::vector<uint8_t> cert_types;
+
+ for(size_t i = 0; i != m_cert_key_types.size(); ++i)
+ cert_types.push_back(cert_type_name_to_code(m_cert_key_types[i]));
+
+ append_tls_length_value(buf, cert_types, 1);
+
+ if(m_schemes.size() > 0)
+ buf += Signature_Algorithms(m_schemes).serialize(Connection_Side::SERVER);
+
+ std::vector<uint8_t> encoded_names;
+
+ for(size_t i = 0; i != m_names.size(); ++i)
+ {
+ DER_Encoder encoder;
+ encoder.encode(m_names[i]);
+
+ append_tls_length_value(encoded_names, encoder.get_contents(), 2);
+ }
+
+ append_tls_length_value(buf, encoded_names, 2);
+
+ return buf;
+ }
+
+}
+
+}