aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/examples/tls_server.cpp66
-rw-r--r--src/cert/x509cert/x509cert.cpp18
-rw-r--r--src/cert/x509cert/x509cert.h6
-rw-r--r--src/credentials/credentials_manager.cpp51
-rw-r--r--src/credentials/credentials_manager.h78
-rw-r--r--src/credentials/info.txt1
-rw-r--r--src/tls/hello.cpp3
-rw-r--r--src/tls/tls_client.cpp45
-rw-r--r--src/tls/tls_client.h17
-rw-r--r--src/tls/tls_magic.h3
-rw-r--r--src/tls/tls_messages.h1
-rw-r--r--src/tls/tls_server.cpp36
-rw-r--r--src/tls/tls_server.h16
13 files changed, 250 insertions, 91 deletions
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp
index d9334c47e..10f294a3f 100644
--- a/doc/examples/tls_server.cpp
+++ b/doc/examples/tls_server.cpp
@@ -16,6 +16,46 @@ using namespace Botan;
#include <iostream>
#include <memory>
+class Credentials_Manager_Simple : public Credentials_Manager
+ {
+ public:
+ Credentials_Manager_Simple(RandomNumberGenerator& rng) : rng(rng) {}
+
+ std::vector<X509_Certificate> cert_chain(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context)
+ {
+ const std::string hostname = (context == "" ? "localhost" : context);
+
+ //RSA_PrivateKey key(rng, 1024);
+ DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024"));
+
+ X509_Cert_Options options(
+ hostname + "/US/Botan Library/Test Server");
+
+ X509_Certificate cert =
+ X509::create_self_signed_cert(options, key, "SHA-1", rng);
+
+ certs_and_keys[cert] = PKCS8::copy_key(key, rng);
+
+ std::vector<X509_Certificate> certs;
+ certs.push_back(cert);
+ return certs;
+ }
+
+ Private_Key* private_key_for(const X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context)
+ {
+ return certs_and_keys[cert];
+ }
+
+ private:
+ RandomNumberGenerator& rng;
+ std::map<X509_Certificate, Private_Key*> certs_and_keys;
+ };
+
void handshake_complete(const TLS_Session& session)
{
printf("Handshake complete, protocol=%04X ciphersuite=%04X compression=%d\n",
@@ -32,20 +72,18 @@ class Blocking_TLS_Server
Blocking_TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn,
std::tr1::function<size_t (byte[], size_t)> input_fn,
TLS_Session_Manager& sessions,
+ Credentials_Manager& creds,
TLS_Policy& policy,
- RandomNumberGenerator& rng,
- const X509_Certificate& cert,
- const Private_Key& key) :
+ RandomNumberGenerator& rng) :
input_fn(input_fn),
server(
output_fn,
std::tr1::bind(&Blocking_TLS_Server::reader_fn, std::tr1::ref(*this), _1, _2, _3),
handshake_complete,
sessions,
+ creds,
policy,
- rng,
- cert,
- key),
+ rng),
exit(false)
{
read_loop();
@@ -154,21 +192,14 @@ int main(int argc, char* argv[])
AutoSeeded_RNG rng;
- RSA_PrivateKey key(rng, 1024);
- //DSA_PrivateKey key(rng, DL_Group("dsa/jce/1024"));
-
- X509_Cert_Options options(
- "localhost/US/Botan Library/Test Server");
-
- X509_Certificate cert =
- X509::create_self_signed_cert(options, key, "SHA-1", rng);
-
Server_Socket listener(port);
Server_TLS_Policy policy;
TLS_Session_Manager_In_Memory sessions;
+ Credentials_Manager_Simple creds(rng);
+
while(true)
{
try {
@@ -182,10 +213,9 @@ int main(int argc, char* argv[])
std::tr1::bind(&Socket::write, std::tr1::ref(sock), _1, _2),
std::tr1::bind(&Socket::read, std::tr1::ref(sock), _1, _2, true),
sessions,
+ creds,
policy,
- rng,
- cert,
- key);
+ rng);
const char* msg = "Welcome to the best echo server evar\n";
tls.write((const Botan::byte*)msg, strlen(msg));
diff --git a/src/cert/x509cert/x509cert.cpp b/src/cert/x509cert/x509cert.cpp
index 7d9370f2a..88aeebd77 100644
--- a/src/cert/x509cert/x509cert.cpp
+++ b/src/cert/x509cert/x509cert.cpp
@@ -296,6 +296,24 @@ bool X509_Certificate::operator==(const X509_Certificate& other) const
subject == other.subject);
}
+bool X509_Certificate::operator<(const X509_Certificate& other) const
+ {
+ /* If signature values are not equal, sort by lexicographic ordering of that */
+ if(sig != other.sig)
+ {
+ if(sig < other.sig)
+ return true;
+ return false;
+ }
+
+ /*
+ * same signatures, highly unlikely case, revert to compare
+ * of entire contents
+ */
+
+ return to_string() < other.to_string();
+ }
+
/*
* X.509 Certificate Comparison
*/
diff --git a/src/cert/x509cert/x509cert.h b/src/cert/x509cert/x509cert.h
index 8798ef1c2..cd49aa02f 100644
--- a/src/cert/x509cert/x509cert.h
+++ b/src/cert/x509cert/x509cert.h
@@ -152,6 +152,12 @@ class BOTAN_DLL X509_Certificate : public X509_Object
bool operator==(const X509_Certificate& other) const;
/**
+ * Impose an arbitrary (but consistent) ordering
+ * @return true if this is less than other by some unspecified criteria
+ */
+ bool operator<(const X509_Certificate& other) const;
+
+ /**
* Create a certificate from a data source providing the DER or
* PEM encoded certificate.
* @param source the data source
diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp
new file mode 100644
index 000000000..46d9e300c
--- /dev/null
+++ b/src/credentials/credentials_manager.cpp
@@ -0,0 +1,51 @@
+/*
+* Credentials Manager
+* (C) 2011,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/credentials_manager.h>
+
+namespace Botan {
+
+std::string Credentials_Manager::srp_identifier(const std::string& type,
+ const std::string& context)
+ {
+ return "";
+ }
+
+std::string Credentials_Manager::srp_password(const std::string& identifier,
+ const std::string& type,
+ const std::string& context)
+ {
+ return "";
+ }
+
+bool Credentials_Manager::srp_verifier(const std::string& identifier,
+ const std::string& type,
+ const std::string& context,
+ BigInt& group_prime,
+ BigInt& group_generator,
+ BigInt& verifier,
+ MemoryRegion<byte>& salt)
+ {
+ return false;
+ }
+
+std::vector<X509_Certificate> Credentials_Manager::cert_chain(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context)
+ {
+ return std::vector<X509_Certificate>();
+ }
+
+Private_Key* Credentials_Manager::private_key_for(const X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context)
+ {
+ return 0;
+ }
+
+}
diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h
new file mode 100644
index 000000000..a54b2ec31
--- /dev/null
+++ b/src/credentials/credentials_manager.h
@@ -0,0 +1,78 @@
+/*
+* Credentials Manager
+* (C) 2011,2012 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_CREDENTIALS_MANAGER_H__
+#define BOTAN_CREDENTIALS_MANAGER_H__
+
+#include <botan/x509cert.h>
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+class BigInt;
+
+/**
+* Interface for a credentials manager.
+*
+* A type is a fairly static value that represents the general nature
+* of the transaction occuring. Currently defined are "tls-client" and
+* "tls-server". Context represents a hostname, email address,
+* username, or other identifier.
+*/
+class BOTAN_DLL Credentials_Manager
+ {
+ public:
+ virtual ~Credentials_Manager() {}
+
+ /**
+ * @return identifier for client-side SRP auth, if available
+ for this type/context
+ */
+ virtual std::string srp_identifier(const std::string& type,
+ const std::string& context);
+
+ /**
+ * @return password for client-side SRP auth, if available
+ for this identifier/type/context
+ */
+ virtual std::string srp_password(const std::string& identifier,
+ const std::string& type,
+ const std::string& context);
+
+ /**
+ * @todo add option for faking verifier if identifier is unknown
+ */
+ virtual bool srp_verifier(const std::string& identifier,
+ const std::string& type,
+ const std::string& context,
+ BigInt& group_prime,
+ BigInt& group_generator,
+ BigInt& verifier,
+ MemoryRegion<byte>& salt);
+
+ /**
+ * @param cert_key_type is a string representing the key type
+ * ("RSA", "DSA", "ECDSA") or empty if no preference.
+ */
+ virtual std::vector<X509_Certificate> cert_chain(
+ const std::string& cert_key_type,
+ const std::string& type,
+ const std::string& context);
+
+ /**
+ * @return private key associated with this certificate if we should
+ * use it with this context
+ */
+ virtual Private_Key* private_key_for(const X509_Certificate& cert,
+ const std::string& type,
+ const std::string& context);
+ };
+
+}
+
+#endif
diff --git a/src/credentials/info.txt b/src/credentials/info.txt
new file mode 100644
index 000000000..f6dcdd64d
--- /dev/null
+++ b/src/credentials/info.txt
@@ -0,0 +1 @@
+define CREDENTIALS_MANAGER
diff --git a/src/tls/hello.cpp b/src/tls/hello.cpp
index 49115fd62..17a624381 100644
--- a/src/tls/hello.cpp
+++ b/src/tls/hello.cpp
@@ -282,10 +282,9 @@ Server_Hello::Server_Hello(Record_Writer& writer,
const MemoryRegion<byte>& reneg_info,
const std::vector<X509_Certificate>& certs,
const Client_Hello& c_hello,
- const MemoryRegion<byte>& session_id,
Version_Code ver) :
s_version(ver),
- sess_id(session_id),
+ sess_id(rng.random_vec(32)),
s_random(rng.random_vec(32)),
m_fragment_size(c_hello.fragment_size()),
has_secure_renegotiation(client_has_secure_renegotiation),
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 1d9554ee8..b7249081b 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -22,21 +22,23 @@ TLS_Client::TLS_Client(std::tr1::function<void (const byte[], size_t)> output_fn
std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn,
std::tr1::function<void (const TLS_Session&)> handshake_fn,
TLS_Session_Manager& session_manager,
+ Credentials_Manager& creds,
const TLS_Policy& policy,
RandomNumberGenerator& rng,
- const std::string& hostname,
- const std::string& srp_identifier,
- const std::string& srp_password) :
+ const std::string& hostname) :
TLS_Channel(output_fn, proc_fn, handshake_fn),
policy(policy),
rng(rng),
- session_manager(session_manager)
+ session_manager(session_manager),
+ creds(creds)
{
writer.set_version(SSL_V3);
state = new Handshake_State;
state->set_expected_next(SERVER_HELLO);
+ const std::string srp_identifier = creds.srp_identifier("tls-client", hostname);
+
if(hostname != "")
{
TLS_Session session_info;
@@ -70,21 +72,6 @@ TLS_Client::TLS_Client(std::tr1::function<void (const byte[], size_t)> output_fn
secure_renegotiation.update(state->client_hello);
}
-void TLS_Client::add_client_cert(const X509_Certificate& cert,
- Private_Key* cert_key)
- {
- certs.push_back(std::make_pair(cert, cert_key));
- }
-
-/*
-* TLS Client Destructor
-*/
-TLS_Client::~TLS_Client()
- {
- for(size_t i = 0; i != certs.size(); i++)
- delete certs[i].second;
- }
-
/*
* Send a new client hello to renegotiate
*/
@@ -308,17 +295,19 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
state->server_hello_done = new Server_Hello_Done(contents);
- std::vector<X509_Certificate> send_certs;
-
if(state->received_handshake_msg(CERTIFICATE_REQUEST))
{
std::vector<Certificate_Type> types =
state->cert_req->acceptable_types();
- // FIXME: Fill in useful certs here, if any
+ std::vector<X509_Certificate> client_certs =
+ creds.cert_chain("", // use types here
+ "tls-client",
+ state->client_hello->sni_hostname());
+
state->client_certs = new Certificate(writer,
state->hash,
- send_certs);
+ client_certs);
}
state->client_kex =
@@ -327,11 +316,15 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
state->client_hello->version());
if(state->received_handshake_msg(CERTIFICATE_REQUEST) &&
- !send_certs.empty())
+ !state->client_certs->empty())
{
- Private_Key* key_matching_cert = 0; // FIXME
+ Private_Key* private_key =
+ creds.private_key_for(state->client_certs->cert_chain()[0],
+ "tls-client",
+ state->client_hello->sni_hostname());
+
state->client_verify = new Certificate_Verify(writer, state->hash,
- rng, key_matching_cert);
+ rng, private_key);
}
state->keys = SessionKeys(state->suite, state->version,
diff --git a/src/tls/tls_client.h b/src/tls/tls_client.h
index eccddef6f..543dda144 100644
--- a/src/tls/tls_client.h
+++ b/src/tls/tls_client.h
@@ -10,6 +10,7 @@
#include <botan/tls_channel.h>
#include <botan/tls_session_manager.h>
+#include <botan/credentials_manager.h>
#include <vector>
namespace Botan {
@@ -26,28 +27,21 @@ class BOTAN_DLL TLS_Client : public TLS_Channel
* @param proc_fn is called when new data (application or alerts) is received
* @param handshake_complete is called when a handshake is completed
* @param session_manager manages session state
+ * @param creds manages application/user credentials
* @param policy specifies other connection policy information
* @param rng a random number generator
* @param servername the server's DNS name, if known
- * @param srp_username a SRP identifier to use for SRP key exchange
- * @param srp_password a SRP password to use for SRP key exchange
*/
TLS_Client(std::tr1::function<void (const byte[], size_t)> socket_output_fn,
std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn,
std::tr1::function<void (const TLS_Session&)> handshake_complete,
TLS_Session_Manager& session_manager,
+ Credentials_Manager& creds,
const TLS_Policy& policy,
RandomNumberGenerator& rng,
- const std::string& servername = "",
- const std::string& srp_username = "",
- const std::string& srp_password = "");
-
- void add_client_cert(const X509_Certificate& cert,
- Private_Key* cert_key);
+ const std::string& servername = "");
void renegotiate();
-
- ~TLS_Client();
private:
void process_handshake_msg(Handshake_Type type,
const MemoryRegion<byte>& contents);
@@ -55,8 +49,7 @@ class BOTAN_DLL TLS_Client : public TLS_Channel
const TLS_Policy& policy;
RandomNumberGenerator& rng;
TLS_Session_Manager& session_manager;
-
- std::vector<std::pair<X509_Certificate, Private_Key*> > certs;
+ Credentials_Manager& creds;
};
}
diff --git a/src/tls/tls_magic.h b/src/tls/tls_magic.h
index 3629cd112..d49ec1e48 100644
--- a/src/tls/tls_magic.h
+++ b/src/tls/tls_magic.h
@@ -164,11 +164,12 @@ enum TLS_Ciphersuite_Algos {
TLS_ALGO_SIGNER_ECDSA = 0x04000000,
TLS_ALGO_KEYEXCH_MASK = 0x00FF0000,
- TLS_ALGO_KEYEXCH_NOKEX = 0x00010000,
+ TLS_ALGO_KEYEXCH_NOKEX = 0x00010000, // exchange via key in server cert
TLS_ALGO_KEYEXCH_RSA = 0x00020000,
TLS_ALGO_KEYEXCH_DH = 0x00030000,
TLS_ALGO_KEYEXCH_ECDH = 0x00040000,
TLS_ALGO_KEYEXCH_SRP = 0x00050000,
+ TLS_ALGO_KEYEXCH_ANON = 0x00060000,
TLS_ALGO_MAC_MASK = 0x0000FF00,
TLS_ALGO_MAC_MD5 = 0x00000100,
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index f0620003b..16069f048 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -150,7 +150,6 @@ class Server_Hello : public Handshake_Message
const MemoryRegion<byte>& reneg_info,
const std::vector<X509_Certificate>& certs,
const Client_Hello& other,
- const MemoryRegion<byte>& session_id,
Version_Code version);
Server_Hello(Record_Writer& writer,
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index 0e2e173cf..b981bdc69 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -85,25 +85,15 @@ TLS_Server::TLS_Server(std::tr1::function<void (const byte[], size_t)> output_fn
std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn,
std::tr1::function<void (const TLS_Session&)> handshake_fn,
TLS_Session_Manager& session_manager,
+ Credentials_Manager& creds,
const TLS_Policy& policy,
- RandomNumberGenerator& rng,
- const X509_Certificate& cert,
- const Private_Key& cert_key) :
+ RandomNumberGenerator& rng) :
TLS_Channel(output_fn, proc_fn, handshake_fn),
policy(policy),
rng(rng),
- session_manager(session_manager)
+ session_manager(session_manager),
+ creds(creds)
{
- cert_chain.push_back(cert);
- private_key = PKCS8::copy_key(cert_key, rng);
- }
-
-/*
-* TLS Server Destructor
-*/
-TLS_Server::~TLS_Server()
- {
- delete private_key;
}
/*
@@ -183,7 +173,6 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
{
// resume session
- printf("Resuming a session\n");
state->server_hello = new Server_Hello(
writer,
state->hash,
@@ -222,6 +211,17 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
}
else // new session
{
+ std::vector<X509_Certificate> server_certs =
+ creds.cert_chain("",
+ "tls-server",
+ client_requested_hostname);
+
+ Private_Key* private_key =
+ server_certs.empty() ? 0 :
+ (creds.private_key_for(server_certs[0],
+ "tls-server",
+ client_requested_hostname));
+
state->server_hello = new Server_Hello(
writer,
state->hash,
@@ -229,9 +229,8 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
rng,
secure_renegotiation.supported(),
secure_renegotiation.for_server_hello(),
- cert_chain,
+ server_certs,
*(state->client_hello),
- rng.random_vec(32),
state->version);
if(state->client_hello->fragment_size())
@@ -241,10 +240,9 @@ void TLS_Server::process_handshake_msg(Handshake_Type type,
if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON)
{
- // FIXME: should choose certs based on sig type
state->server_certs = new Certificate(writer,
state->hash,
- cert_chain);
+ server_certs);
}
if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_NOKEX)
diff --git a/src/tls/tls_server.h b/src/tls/tls_server.h
index d684a4a11..e07f89eba 100644
--- a/src/tls/tls_server.h
+++ b/src/tls/tls_server.h
@@ -10,6 +10,7 @@
#include <botan/tls_channel.h>
#include <botan/tls_session_manager.h>
+#include <botan/credentials_manager.h>
#include <vector>
namespace Botan {
@@ -20,23 +21,16 @@ namespace Botan {
class BOTAN_DLL TLS_Server : public TLS_Channel
{
public:
-
/**
* TLS_Server initialization
- *
- * FIXME: support cert chains (!)
- * FIXME: support anonymous servers
*/
TLS_Server(std::tr1::function<void (const byte[], size_t)> socket_output_fn,
std::tr1::function<void (const byte[], size_t, u16bit)> proc_fn,
std::tr1::function<void (const TLS_Session&)> handshake_complete,
TLS_Session_Manager& session_manager,
+ Credentials_Manager& creds,
const TLS_Policy& policy,
- RandomNumberGenerator& rng,
- const X509_Certificate& cert,
- const Private_Key& cert_key);
-
- ~TLS_Server();
+ RandomNumberGenerator& rng);
void renegotiate();
@@ -53,9 +47,7 @@ class BOTAN_DLL TLS_Server : public TLS_Channel
const TLS_Policy& policy;
RandomNumberGenerator& rng;
TLS_Session_Manager& session_manager;
-
- std::vector<X509_Certificate> cert_chain;
- Private_Key* private_key;
+ Credentials_Manager& creds;
std::string client_requested_hostname;
};