ssl works now

svn path=/trunk/kdesupport/qca/; revision=407592
This commit is contained in:
Justin Karneges 2005-04-24 19:09:06 +00:00
parent 171f3b97a6
commit db68d7059e
4 changed files with 342 additions and 116 deletions

View File

@ -68,7 +68,7 @@ namespace QCA
// encoded (network side) // encoded (network side)
virtual void writeIncoming(const QByteArray &a) = 0; virtual void writeIncoming(const QByteArray &a) = 0;
virtual QByteArray readOutgoing(int *plainBytes = 0) = 0; virtual QByteArray readOutgoing(int *plainBytes = 0) = 0;
virtual QSecureArray readUnprocessed(); virtual QByteArray readUnprocessed();
}; };
// securelayer - "nicer" interface, using signals. subclass // securelayer - "nicer" interface, using signals. subclass
@ -110,15 +110,15 @@ namespace QCA
}; };
enum Error enum Error
{ {
ErrHandshake, ///< problem during the negotiation ErrorHandshake, ///< problem during the negotiation
ErrCrypt ///< problem at anytime after ErrorCrypt ///< problem at anytime after
}; };
enum IdentityResult enum IdentityResult
{ {
Valid, ///< identity is verified Valid, ///< identity is verified
HostMismatch, ///< valid cert provided, but wrong owner HostMismatch, ///< valid cert provided, but wrong owner
BadCert, ///< invalid cert InvalidCertificate, ///< invalid cert
NoCert ///< identity unknown NoCertificate ///< identity unknown
}; };
TLS(QObject *parent = 0, const QString &provider = QString()); TLS(QObject *parent = 0, const QString &provider = QString());
@ -164,7 +164,7 @@ namespace QCA
virtual QSecureArray read(); virtual QSecureArray read();
virtual void writeIncoming(const QByteArray &a); virtual void writeIncoming(const QByteArray &a);
virtual QByteArray readOutgoing(int *plainBytes = 0); virtual QByteArray readOutgoing(int *plainBytes = 0);
virtual QSecureArray readUnprocessed(); virtual QByteArray readUnprocessed();
signals: signals:
void handshaken(); void handshaken();

View File

@ -431,6 +431,7 @@ public:
virtual QStringList supportedCipherSuites() const = 0; virtual QStringList supportedCipherSuites() const = 0;
virtual bool canCompress() const = 0; virtual bool canCompress() const = 0;
virtual int maxSSF() const = 0;
virtual void setConstraints(int minSSF, int maxSSF) = 0; virtual void setConstraints(int minSSF, int maxSSF) = 0;
virtual void setConstraints(const QStringList &cipherSuiteList) = 0; virtual void setConstraints(const QStringList &cipherSuiteList) = 0;
@ -445,7 +446,7 @@ public:
virtual bool decode(const QByteArray &from_net, QSecureArray *plain, QByteArray *to_net) = 0; virtual bool decode(const QByteArray &from_net, QSecureArray *plain, QByteArray *to_net) = 0;
virtual bool eof() const = 0; virtual bool eof() const = 0;
virtual SessionInfo sessionInfo() const = 0; virtual SessionInfo sessionInfo() const = 0;
virtual QSecureArray unprocessed() = 0; virtual QByteArray unprocessed() = 0;
virtual TLS::IdentityResult peerIdentityResult() const = 0; virtual TLS::IdentityResult peerIdentityResult() const = 0;
virtual Validity peerCertificateValidity() const = 0; virtual Validity peerCertificateValidity() const = 0;

View File

@ -3438,6 +3438,12 @@ public:
return false; return false;
} }
virtual int maxSSF() const
{
// TODO
return 256;
}
virtual void setConstraints(int minSSF, int maxSSF) virtual void setConstraints(int minSSF, int maxSSF)
{ {
// TODO // TODO
@ -3454,7 +3460,8 @@ public:
virtual void setup(const QCA::CertificateCollection &_trusted, const QCA::CertificateChain &_cert, const QCA::PrivateKey &_key, bool compress) virtual void setup(const QCA::CertificateCollection &_trusted, const QCA::CertificateChain &_cert, const QCA::PrivateKey &_key, bool compress)
{ {
trusted = _trusted; trusted = _trusted;
cert = _cert.primary(); // TODO: take the whole chain if(!_cert.isEmpty())
cert = _cert.primary(); // TODO: take the whole chain
key = _key; key = _key;
Q_UNUSED(compress); // TODO Q_UNUSED(compress); // TODO
} }
@ -3662,9 +3669,9 @@ public:
return SessionInfo(); return SessionInfo();
} }
virtual QSecureArray unprocessed() virtual QByteArray unprocessed()
{ {
QSecureArray a; QByteArray a;
int size = BIO_pending(rbio); int size = BIO_pending(rbio);
if(size <= 0) if(size <= 0)
return a; return a;

View File

@ -22,11 +22,12 @@
#include "qca_securelayer.h" #include "qca_securelayer.h"
#include <QtCore> #include <QtCore>
//#include <qhostaddress.h>
#include "qcaprovider.h" #include "qcaprovider.h"
namespace QCA { namespace QCA {
Provider::Context *getContext(const QString &type, const QString &provider);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// SecureFilter // SecureFilter
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -48,9 +49,9 @@ void SecureFilter::close()
{ {
} }
QSecureArray SecureFilter::readUnprocessed() QByteArray SecureFilter::readUnprocessed()
{ {
return QSecureArray(); return QByteArray();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -79,9 +80,9 @@ void SecureLayer::layerUpdateEnd()
{ {
if(_signals) if(_signals)
{ {
if(_read > bytesAvailable()) if(bytesAvailable() > _read)
QTimer::singleShot(0, this, SIGNAL(readyRead())); QTimer::singleShot(0, this, SIGNAL(readyRead()));
if(_readout > bytesOutgoingAvailable()) if(bytesOutgoingAvailable() > _readout)
QTimer::singleShot(0, this, SIGNAL(readyReadOutgoing())); QTimer::singleShot(0, this, SIGNAL(readyReadOutgoing()));
if(!_closed && haveClosed()) if(!_closed && haveClosed())
QTimer::singleShot(0, this, SIGNAL(closed())); QTimer::singleShot(0, this, SIGNAL(closed()));
@ -93,58 +94,251 @@ void SecureLayer::layerUpdateEnd()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// TLS // TLS
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
enum ResetMode
{
ResetSession = 0,
ResetSessionAndData = 1,
ResetAll = 2
};
class TLS::Private class TLS::Private
{ {
public: public:
Private() TLS *q;
{
//store = 0;
}
void reset()
{
handshaken = false;
closing = false;
in.resize(0);
out.resize(0);
from_net.resize(0);
to_net.resize(0);
host = QString();
hostMismatch = false;
cert = Certificate();
bytesEncoded = 0;
tryMore = false;
}
void appendArray(QByteArray *a, const QByteArray &b)
{
int oldsize = a->size();
a->resize(oldsize + b.size());
memcpy(a->data() + oldsize, b.data(), b.size());
}
Certificate cert;
Validity certValidity;
TLSContext *c; TLSContext *c;
QByteArray in, out, to_net, from_net;
int bytesEncoded; CertificateChain localCert;
bool tryMore; PrivateKey localKey;
bool handshaken; CertificateCollection trusted;
bool con_ssfMode;
int con_minSSF, con_maxSSF;
QStringList con_cipherSuites;
bool tryCompress;
QString host; QString host;
CertificateChain peerCert;
Validity peerValidity;
bool hostMismatch; bool hostMismatch;
bool closing; TLSContext::SessionInfo sessionInfo;
QSecureArray in, out;
QByteArray to_net, from_net;
bool handshaken, closing, closed, error;
bool tryMore;
int bytesEncoded;
Error errorCode; Error errorCode;
Certificate ourCert; Private(TLS *_q)
PrivateKey ourKey; {
//Store *store; q = _q;
c = 0;
reset(ResetAll);
}
void reset(ResetMode mode = ResetSession)
{
if(c)
c->reset();
host = QString();
out.clear();
handshaken = false;
closing = false;
closed = false;
error = false;
tryMore = false;
bytesEncoded = 0;
if(mode >= ResetSessionAndData)
{
peerCert = CertificateChain();
in.clear();
to_net.clear();
from_net.clear();
}
if(mode >= ResetAll)
{
localCert = CertificateChain();
localKey = PrivateKey();
trusted = CertificateCollection();
con_ssfMode = true;
con_minSSF = 128;
con_maxSSF = -1;
con_cipherSuites = QStringList();
tryCompress = false;
}
}
bool start(bool serverMode)
{
if(con_ssfMode)
c->setConstraints(con_minSSF, con_maxSSF);
else
c->setConstraints(con_cipherSuites);
c->setup(trusted, localCert, localKey, tryCompress);
bool ok;
if(serverMode)
ok = c->startServer();
else
ok = c->startClient();
if(!ok)
return false;
update();
return true;
}
void close()
{
if(!handshaken || closing)
return;
closing = true;
}
void update()
{
bool wasHandshaken = handshaken;
q->layerUpdateBegin();
if(closing)
updateClosing();
else
updateMain();
if(!wasHandshaken && handshaken)
QTimer::singleShot(0, q, SIGNAL(handshaken()));
q->layerUpdateEnd();
}
void updateClosing()
{
QByteArray a;
TLSContext::Result r = c->shutdown(from_net, &a);
from_net.clear();
if(r == TLSContext::Error)
{
reset();
error = true;
errorCode = ErrorHandshake;
return;
}
to_net.append(a);
if(r == TLSContext::Success)
{
from_net = c->unprocessed();
reset();
closed = true;
return;
}
}
void updateMain()
{
bool force_read = false;
if(!handshaken)
{
QByteArray a;
TLSContext::Result r = c->handshake(from_net, &a);
from_net.clear();
if(r == TLSContext::Error)
{
reset();
error = true;
errorCode = ErrorHandshake;
return;
}
to_net.append(a);
if(r == TLSContext::Success)
{
peerCert = c->peerCertificateChain();
if(!peerCert.isEmpty())
{
peerValidity = c->peerCertificateValidity();
if(peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostname(host))
hostMismatch = true;
}
handshaken = true;
force_read = true;
}
}
if(handshaken)
{
bool eof = false;
if(!out.isEmpty() || tryMore)
{
tryMore = false;
QByteArray a;
int enc;
bool more = false;
bool ok = c->encode(out, &a, &enc);
eof = c->eof();
if(ok && enc < out.size())
more = true;
out.clear();
if(!eof)
{
if(!ok)
{
reset();
error = true;
errorCode = ErrorCrypt;
return;
}
bytesEncoded += enc;
if(more)
tryMore = true;
to_net.append(a);
}
}
if(!from_net.isEmpty() || force_read)
{
QSecureArray a;
QByteArray b;
bool ok = c->decode(from_net, &a, &b);
eof = c->eof();
from_net.clear();
if(!ok)
{
reset();
error = true;
errorCode = ErrorCrypt;
return;
}
in.append(a);
to_net.append(b);
}
if(eof)
{
close();
updateClosing();
return;
}
}
}
}; };
TLS::TLS(QObject *parent, const QString &provider) TLS::TLS(QObject *parent, const QString &provider)
:SecureLayer(parent), Algorithm("tls", provider) :SecureLayer(parent), Algorithm("tls", provider)
{ {
d = new Private; d = new Private(this);
d->c = (TLSContext *)context(); d->c = static_cast<TLSContext *>(context());
} }
TLS::~TLS() TLS::~TLS()
@ -154,73 +348,100 @@ TLS::~TLS()
void TLS::reset() void TLS::reset()
{ {
d->reset(); d->reset(ResetAll);
// TODO: d->c->reset ??
} }
QStringList TLS::supportedCipherSuites(const QString &provider) QStringList TLS::supportedCipherSuites(const QString &provider)
{ {
Q_UNUSED(provider); QStringList list;
return QStringList(); const TLSContext *c = static_cast<const TLSContext *>(getContext("tls", provider));
if(!c)
return list;
list = c->supportedCipherSuites();
delete c;
return list;
} }
void TLS::setCertificate(const CertificateChain &cert, const PrivateKey &key) void TLS::setCertificate(const CertificateChain &cert, const PrivateKey &key)
{ {
Q_UNUSED(cert); d->localCert = cert;
//d->ourCert = cert; d->localKey = key;
d->ourKey = key;
} }
void TLS::setTrustedCertificates(const CertificateCollection &trusted) void TLS::setTrustedCertificates(const CertificateCollection &trusted)
{ {
Q_UNUSED(trusted); d->trusted = trusted;
//d->store = new Store(store);
} }
void TLS::setConstraints(SecurityLevel s) void TLS::setConstraints(SecurityLevel s)
{ {
Q_UNUSED(s); int min;
switch(s)
{
case SL_None:
min = 0;
break;
case SL_Integrity:
min = 1;
break;
case SL_Export:
min = 40;
break;
case SL_Baseline:
min = 128;
break;
case SL_High:
min = 129;
break;
case SL_Highest:
qMax(129, d->c->maxSSF());
break;
}
d->con_ssfMode = true;
d->con_minSSF = min;
d->con_maxSSF = -1;
} }
void TLS::setConstraints(int, int) void TLS::setConstraints(int minSSF, int maxSSF)
{ {
d->con_ssfMode = true;
d->con_minSSF = minSSF;
d->con_maxSSF = maxSSF;
} }
void TLS::setConstraints(const QStringList &cipherSuiteList) void TLS::setConstraints(const QStringList &cipherSuiteList)
{ {
Q_UNUSED(cipherSuiteList); d->con_ssfMode = false;
d->con_cipherSuites = cipherSuiteList;
} }
bool TLS::canCompress(const QString &provider) bool TLS::canCompress(const QString &provider)
{ {
Q_UNUSED(provider); bool ok = false;
return false; const TLSContext *c = static_cast<const TLSContext *>(getContext("tls", provider));
if(!c)
return ok;
ok = c->canCompress();
delete c;
return ok;
} }
void TLS::setCompressionEnabled(bool b) void TLS::setCompressionEnabled(bool b)
{ {
Q_UNUSED(b); d->tryCompress = b;
} }
bool TLS::startClient(const QString &host) bool TLS::startClient(const QString &host)
{ {
d->reset(); d->reset(ResetSessionAndData);
d->host = host; d->host = host;
return d->start(false);
/*if(!d->c->startClient(*((StoreContext *)d->store->context()), *((CertContext *)d->ourCert.context()), *((PKeyContext *)d->ourKey.context())))
return false;
QTimer::singleShot(0, this, SLOT(update()));*/
return true;
} }
bool TLS::startServer() bool TLS::startServer()
{ {
d->reset(); d->reset(ResetSessionAndData);
return d->start(true);
/*if(!d->c->startServer(*((StoreContext *)d->store->context()), *((CertContext *)d->ourCert.context()), *((PKeyContext *)d->ourKey.context())))
return false;
QTimer::singleShot(0, this, SLOT(update()));*/
return true;
} }
bool TLS::isHandshaken() const bool TLS::isHandshaken() const
@ -230,27 +451,27 @@ bool TLS::isHandshaken() const
bool TLS::isCompressed() const bool TLS::isCompressed() const
{ {
return false; return d->sessionInfo.isCompressed;
} }
TLS::Version TLS::version() const TLS::Version TLS::version() const
{ {
return TLS_v1; return d->sessionInfo.version;
} }
QString TLS::cipherSuite() const QString TLS::cipherSuite() const
{ {
return QString(); return d->sessionInfo.cipherSuite;
} }
int TLS::cipherBits() const int TLS::cipherBits() const
{ {
return 0; return d->sessionInfo.cipherBits;
} }
int TLS::cipherMaxBits() const int TLS::cipherMaxBits() const
{ {
return 0; return d->sessionInfo.cipherMaxBits;
} }
TLS::Error TLS::errorCode() const TLS::Error TLS::errorCode() const
@ -260,11 +481,11 @@ TLS::Error TLS::errorCode() const
TLS::IdentityResult TLS::peerIdentityResult() const TLS::IdentityResult TLS::peerIdentityResult() const
{ {
if(d->cert.isNull()) if(d->peerCert.isEmpty())
return NoCert; return NoCertificate;
//if(d->certValidity != QCA::Valid) if(d->peerValidity != ValidityGood)
// return BadCert; return InvalidCertificate;
if(d->hostMismatch) if(d->hostMismatch)
return HostMismatch; return HostMismatch;
@ -274,19 +495,17 @@ TLS::IdentityResult TLS::peerIdentityResult() const
Validity TLS::peerCertificateValidity() const Validity TLS::peerCertificateValidity() const
{ {
return d->certValidity; return d->peerValidity;
} }
CertificateChain TLS::localCertificateChain() const CertificateChain TLS::localCertificateChain() const
{ {
return CertificateChain(); return d->localCert;
//return d->ourCert;
} }
CertificateChain TLS::peerCertificateChain() const CertificateChain TLS::peerCertificateChain() const
{ {
return CertificateChain(); return d->peerCert;
//return d->cert;
} }
bool TLS::isClosable() const bool TLS::isClosable() const
@ -296,64 +515,63 @@ bool TLS::isClosable() const
bool TLS::haveClosed() const bool TLS::haveClosed() const
{ {
return false; return d->closed;
} }
bool TLS::ok() const bool TLS::ok() const
{ {
return false; return !d->error;
} }
int TLS::bytesAvailable() const int TLS::bytesAvailable() const
{ {
return 0; return d->in.size();
} }
int TLS::bytesOutgoingAvailable() const int TLS::bytesOutgoingAvailable() const
{ {
return 0; return d->to_net.size();
} }
void TLS::close() void TLS::close()
{ {
if(!d->handshaken || d->closing) d->close();
return; d->update();
d->closing = true;
QTimer::singleShot(0, this, SLOT(update()));
} }
void TLS::write(const QSecureArray &a) void TLS::write(const QSecureArray &a)
{ {
d->appendArray(&d->out, a.toByteArray()); d->out.append(a);
//update(); d->update();
} }
QSecureArray TLS::read() QSecureArray TLS::read()
{ {
QByteArray a = d->in; QSecureArray a = d->in;
d->in.resize(0); d->in.clear();
return a; return a;
} }
void TLS::writeIncoming(const QByteArray &a) void TLS::writeIncoming(const QByteArray &a)
{ {
d->appendArray(&d->from_net, a); d->from_net.append(a);
//update(); d->update();
} }
QByteArray TLS::readOutgoing(int *plainBytes) QByteArray TLS::readOutgoing(int *plainBytes)
{ {
Q_UNUSED(plainBytes);
QByteArray a = d->to_net; QByteArray a = d->to_net;
d->to_net.resize(0); d->to_net.clear();
if(plainBytes)
*plainBytes = d->bytesEncoded;
d->bytesEncoded = 0;
return a; return a;
} }
QSecureArray TLS::readUnprocessed() QByteArray TLS::readUnprocessed()
{ {
QByteArray a = d->from_net; QByteArray a = d->from_net;
d->from_net.resize(0); d->from_net.clear();
return a; return a;
} }