mirror of
https://github.com/QuasarApp/qca.git
synced 2025-05-10 09:49:33 +00:00
keystore API for accessing system stores, smart cards, and pgp
svn path=/trunk/kdesupport/qca/; revision=401186
This commit is contained in:
parent
7033275a3a
commit
ab508f9893
6
TODO
6
TODO
@ -22,9 +22,12 @@
|
||||
give all classes non-default ctors/dtors/copy/op=, and dpointers?
|
||||
|
||||
* finish API:
|
||||
make systemstore work via keystore
|
||||
pkey: ability to get the bitsize of a key
|
||||
cert: subject/issuer key ids?
|
||||
cert: use info as a multi-map?
|
||||
pgp: get key types and bits?
|
||||
dlgroup, symmetric key -> make these into provider objects, for smartcards?
|
||||
qcaprovider.h
|
||||
|
||||
* build system:
|
||||
@ -36,6 +39,7 @@
|
||||
|
||||
* finish code for APIs:
|
||||
cert: rfc 2818 hostname validation
|
||||
keystore
|
||||
tls
|
||||
sasl
|
||||
securemessagesystem (consider thread issues)
|
||||
@ -56,10 +60,8 @@
|
||||
figure out why Valgrind reports so many memory leaks
|
||||
|
||||
* possibilities for the future:
|
||||
smart cards (pkcs11/15)
|
||||
xmldsig
|
||||
xmlenc (sort of done already in cutestuff/xmlsec, but need to qca-ify)
|
||||
advanced pgp functionality (full key info and ability to manipulate keyrings)
|
||||
Key wrapping - RFC3217 and RFC3394
|
||||
dtls (secure UDP)
|
||||
quoted-printable TextFilter
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "qca_basic.h"
|
||||
#include "qca_publickey.h"
|
||||
#include "qca_cert.h"
|
||||
#include "qca_keystore.h"
|
||||
#include "qca_securelayer.h"
|
||||
#include "qca_securemessage.h"
|
||||
#include "qcaprovider.h"
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
class CertificateCollection;
|
||||
|
||||
/**
|
||||
Certificate Request Format
|
||||
*/
|
||||
@ -78,6 +80,20 @@ namespace QCA
|
||||
OCSPSigning
|
||||
};
|
||||
|
||||
/**
|
||||
Specify the intended usage of a certificate
|
||||
*/
|
||||
enum UsageMode
|
||||
{
|
||||
UsageAny = 0x00, ///< Any application, or unspecified
|
||||
UsageTLSServer = 0x01, ///< server side of a TLS or SSL connection
|
||||
UsageTLSClient = 0x02, ///< client side of a TLS or SSL connection
|
||||
UsageCodeSigning = 0x04, ///< code signing certificate
|
||||
UsageEmailProtection = 0x08, ///< email (S/MIME) certificate
|
||||
UsageTimeStamping = 0x10, ///< time stamping certificate
|
||||
UsageCRLSigning = 0x20 ///< certificate revocation list signing certificate
|
||||
};
|
||||
|
||||
/**
|
||||
The validity (or otherwise) of a certificate
|
||||
*/
|
||||
@ -164,6 +180,8 @@ namespace QCA
|
||||
QSecureArray signature() const;
|
||||
SignatureAlgorithm signatureAlgorithm() const;
|
||||
|
||||
Validity validate(const CertificateCollection &trusted, const CertificateCollection &untrusted, UsageMode u = UsageAny) const;
|
||||
|
||||
// import / export
|
||||
QSecureArray toDER() const;
|
||||
QString toPEM() const;
|
||||
@ -279,48 +297,35 @@ namespace QCA
|
||||
static CRL fromPEM(const QString &s, ConvertResult *result = 0, const QString &provider = QString());
|
||||
};
|
||||
|
||||
class QCA_EXPORT Store : public Algorithm
|
||||
// a bundle of Certificates and CRLs
|
||||
class CertificateCollection
|
||||
{
|
||||
public:
|
||||
enum TrustMode
|
||||
{
|
||||
Trusted,
|
||||
Untrusted
|
||||
};
|
||||
CertificateCollection();
|
||||
CertificateCollection(const CertificateCollection &from);
|
||||
~CertificateCollection();
|
||||
CertificateCollection & operator=(const CertificateCollection &from);
|
||||
|
||||
/**
|
||||
Specify the intended usage of a certificate
|
||||
*/
|
||||
enum UsageMode
|
||||
{
|
||||
UsageAny = 0x00, ///< Any application, or unspecified
|
||||
UsageTLSServer = 0x01, ///< server side of a TLS or SSL connection
|
||||
UsageTLSClient = 0x02, ///< client side of a TLS or SSL connection
|
||||
UsageCodeSigning = 0x04, ///< code signing certificate
|
||||
UsageEmailProtection = 0x08, ///< email (S/MIME) certificate
|
||||
UsageTimeStamping = 0x10, ///< time stamping certificate
|
||||
UsageCRLSigning = 0x20 ///< certificate revocation list signing certificate
|
||||
};
|
||||
|
||||
Store(const QString &provider = QString());
|
||||
|
||||
void addCertificate(const Certificate &cert, TrustMode t = Untrusted);
|
||||
void addCertificate(const Certificate &cert);
|
||||
void addCRL(const CRL &crl);
|
||||
Validity validate(const Certificate &cert, UsageMode u = UsageAny) const;
|
||||
|
||||
QList<Certificate> certificates() const;
|
||||
QList<CRL> crls() const;
|
||||
|
||||
void append(const CertificateCollection &other);
|
||||
CertificateCollection operator+(const CertificateCollection &other) const;
|
||||
CertificateCollection & operator+=(const CertificateCollection &other);
|
||||
|
||||
// import / export
|
||||
static bool canUsePKCS7(const QString &provider = QString());
|
||||
bool toPKCS7File(const QString &fileName) const;
|
||||
bool toFlatTextFile(const QString &fileName) const;
|
||||
static Store fromPKCS7File(const QString &fileName, TrustMode t = Untrusted, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static Store fromFlatTextFile(const QString &fileName, TrustMode t = Untrusted, ConvertResult *result = 0, const QString &provider = QString());
|
||||
bool toFlatTextFile(const QString &fileName);
|
||||
bool toPKCS7File(const QString &fileName, const QString &provider = QString());
|
||||
static CertificateCollection fromFlatTextFile(const QString &fileName, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static CertificateCollection fromPKCS7File(const QString &fileName, ConvertResult *result = 0, const QString &provider = QString());
|
||||
|
||||
void append(const Store &a);
|
||||
Store operator+(const Store &a) const;
|
||||
Store & operator+=(const Store &a);
|
||||
private:
|
||||
class Private;
|
||||
QSharedDataPointer<Private> d;
|
||||
};
|
||||
|
||||
class QCA_EXPORT CertificateAuthority : public Algorithm
|
||||
@ -336,14 +341,15 @@ namespace QCA
|
||||
CRL updateCRL(const CRL &crl, const QList<CRLEntry> &entries, const QDateTime &nextUpdate) const;
|
||||
};
|
||||
|
||||
class QCA_EXPORT PersonalBundle
|
||||
// holds a certificate chain and an associated private key
|
||||
class QCA_EXPORT KeyBundle
|
||||
{
|
||||
public:
|
||||
PersonalBundle();
|
||||
PersonalBundle(const QString &fileName, const QSecureArray &passphrase);
|
||||
PersonalBundle(const PersonalBundle &from);
|
||||
~PersonalBundle();
|
||||
PersonalBundle & operator=(const PersonalBundle &from);
|
||||
KeyBundle();
|
||||
KeyBundle(const QString &fileName, const QSecureArray &passphrase);
|
||||
KeyBundle(const KeyBundle &from);
|
||||
~KeyBundle();
|
||||
KeyBundle & operator=(const KeyBundle &from);
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
@ -356,12 +362,49 @@ namespace QCA
|
||||
// import / export
|
||||
QByteArray toArray(const QSecureArray &passphrase, const QString &provider = QString()) const;
|
||||
bool toFile(const QString &fileName, const QSecureArray &passphrase, const QString &provider = QString()) const;
|
||||
static PersonalBundle fromArray(const QByteArray &a, const QSecureArray &passphrase, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static PersonalBundle fromFile(const QString &fileName, const QSecureArray &passphrase, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static KeyBundle fromArray(const QByteArray &a, const QSecureArray &passphrase, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static KeyBundle fromFile(const QString &fileName, const QSecureArray &passphrase, ConvertResult *result = 0, const QString &provider = QString());
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
QSharedDataPointer<Private> d;
|
||||
};
|
||||
|
||||
// PGPKey can either reference an item in a real PGP keyring or can
|
||||
// be made by calling a "from" function. Note that with the latter
|
||||
// method, the key is of no use besides being informational. The
|
||||
// key must be in a keyring (inKeyring() == true) to actually do
|
||||
// crypto with it.
|
||||
class QCA_EXPORT PGPKey : public Algorithm
|
||||
{
|
||||
public:
|
||||
PGPKey();
|
||||
PGPKey(const QString &fileName);
|
||||
PGPKey(const PGPKey &from);
|
||||
~PGPKey();
|
||||
PGPKey & operator=(const PGPKey &from);
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
QString keyId() const;
|
||||
QString primaryUserId() const;
|
||||
QStringList userIds() const;
|
||||
|
||||
bool havePrivate() const;
|
||||
QDateTime creationDate() const;
|
||||
QDateTime expirationDate() const;
|
||||
QString fingerprint() const;
|
||||
|
||||
bool inKeyring() const;
|
||||
bool isTrusted() const;
|
||||
|
||||
// import / export
|
||||
QSecureArray toArray() const;
|
||||
QString toString() const;
|
||||
bool toFile(const QString &fileName) const;
|
||||
static PGPKey fromArray(const QSecureArray &a, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static PGPKey fromString(const QString &s, ConvertResult *result = 0, const QString &provider = QString());
|
||||
static PGPKey fromFile(const QString &fileName, ConvertResult *result = 0, const QString &provider = QString());
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,8 @@ namespace QCA
|
||||
{
|
||||
class Provider;
|
||||
class Random;
|
||||
class Store;
|
||||
class CertificateCollection;
|
||||
class KeyStoreManager;
|
||||
|
||||
/**
|
||||
* Convenience representation for the plugin providers
|
||||
@ -323,11 +324,16 @@ namespace QCA
|
||||
*/
|
||||
QCA_EXPORT void setGlobalRNG(const QString &provider);
|
||||
|
||||
/**
|
||||
Return a reference to the KeyStoreManager, which is used to interface with
|
||||
system storage, PGP keyrings, and smart cards.
|
||||
*/
|
||||
QCA_EXPORT KeyStoreManager *keyStoreManager();
|
||||
|
||||
/**
|
||||
Test if QCA can access the root CA certificates
|
||||
|
||||
QCA supports the concept of a Store, containing certificates.
|
||||
If those certificates are available, this function returns true,
|
||||
If root certificates are available, this function returns true,
|
||||
otherwise it returns false.
|
||||
|
||||
\sa systemStore
|
||||
@ -337,11 +343,11 @@ namespace QCA
|
||||
/**
|
||||
Get system-wide root CA certificates
|
||||
|
||||
\param provider a specific provider to generate the Store, if required
|
||||
\param provider a specific provider to generate the CertificateCollection, if required
|
||||
|
||||
\sa haveSystemStore
|
||||
*/
|
||||
QCA_EXPORT Store systemStore(const QString &provider = QString());
|
||||
QCA_EXPORT CertificateCollection systemStore(const QString &provider = QString());
|
||||
|
||||
/**
|
||||
* Get the application name that will be used by SASL server mode
|
||||
|
124
include/QtCrypto/qca_keystore.h
Normal file
124
include/QtCrypto/qca_keystore.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* qca_keystore.h - Qt Cryptographic Architecture
|
||||
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
|
||||
* Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QCA_KEYSTORE_H
|
||||
#define QCA_KEYSTORE_H
|
||||
|
||||
#include "qca_core.h"
|
||||
#include "qca_cert.h"
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
// container for any kind of object in a keystore
|
||||
class QCA_EXPORT KeyStoreEntry : public Algorithm
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
TypeKeyBundle,
|
||||
TypeCertificate,
|
||||
TypeCRL,
|
||||
TypePGPSecretKey,
|
||||
TypePGPPublicKey
|
||||
};
|
||||
|
||||
KeyStoreEntry();
|
||||
KeyStoreEntry(const KeyStoreEntry &from);
|
||||
~KeyStoreEntry();
|
||||
KeyStoreEntry & operator=(const KeyStoreEntry &from);
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
Type type() const;
|
||||
QString name() const;
|
||||
QString id() const;
|
||||
|
||||
KeyBundle keyBundle() const;
|
||||
Certificate certificate() const;
|
||||
CRL crl() const;
|
||||
PGPKey pgpSecretKey() const;
|
||||
PGPKey pgpPublicKey() const;
|
||||
};
|
||||
|
||||
/*
|
||||
systemstore: System TrustedCertificates
|
||||
accepted self-signed: Application TrustedCertificates
|
||||
apple keychain: User Identities
|
||||
smartcard: SmartCard Identities
|
||||
gnupg: PGPKeyring Identities,PGPPublicKeys
|
||||
*/
|
||||
class QCA_EXPORT KeyStore : public Algorithm
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
System, // root certs
|
||||
User, // Apple Keychain, KDE Wallet, and others
|
||||
Application, // for caching accepted self-signed certs
|
||||
SmartCard, // smartcards
|
||||
PGPKeyring // pgp keyring
|
||||
};
|
||||
|
||||
KeyStore();
|
||||
KeyStore(const KeyStore &from);
|
||||
~KeyStore();
|
||||
KeyStore & operator=(const KeyStore &from);
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
Type type() const;
|
||||
QString name() const;
|
||||
QString id() const;
|
||||
bool isReadOnly() const;
|
||||
|
||||
QList<KeyStoreEntry> entryList() const;
|
||||
bool containsTrustedCertificates() const; // Certificate and CRL
|
||||
bool containsIdentities() const; // KeyBundle and PGPSecretKey
|
||||
bool containsPGPPublicKeys() const; // PGPPublicKey
|
||||
|
||||
bool writeEntry(const KeyBundle &kb);
|
||||
bool writeEntry(const Certificate &cert);
|
||||
bool writeEntry(const CRL &crl);
|
||||
PGPKey writeEntry(const PGPKey &key); // returns a ref to the key in the keyring
|
||||
bool removeEntry(const QString &id);
|
||||
};
|
||||
|
||||
// use this to get access to keystores and monitor for their activity
|
||||
class QCA_EXPORT KeyStoreManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyStore keyStore(const QString &id) const;
|
||||
QList<KeyStore> keyStores() const;
|
||||
int count() const;
|
||||
|
||||
signals:
|
||||
void keyStoreAvailable(const QString &id);
|
||||
void keyStoreUnavailable(const QString &id);
|
||||
void keyStoreUpdated(const QString &id);
|
||||
|
||||
private:
|
||||
KeyStoreManager();
|
||||
~KeyStoreManager();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -129,7 +129,7 @@ namespace QCA
|
||||
static QStringList supportedCipherSuites(const QString &provider = QString());
|
||||
|
||||
void setCertificate(const CertificateChain &cert, const PrivateKey &key);
|
||||
void setStore(const Store &store);
|
||||
void setTrustedCertificates(const CertificateCollection &trusted);
|
||||
void setConstraints(SecurityLevel s);
|
||||
void setConstraints(int minSSF, int maxSSF);
|
||||
void setConstraints(const QStringList &cipherSuiteList);
|
||||
|
@ -219,7 +219,7 @@ namespace QCA
|
||||
SMIME(QObject *parent = 0, const QString &provider = QString());
|
||||
~SMIME();
|
||||
|
||||
void setStore(const Store &store);
|
||||
void setTrustedCertificates(const CertificateCollection &trusted); // todo: untrusted?
|
||||
void setPrivateKeys(const QList<PrivateKey> &keys);
|
||||
};
|
||||
}
|
||||
|
@ -266,6 +266,8 @@ public:
|
||||
SignatureAlgorithm sigalgo;
|
||||
};
|
||||
|
||||
class CRLContext;
|
||||
|
||||
class CertContext : public CertBase
|
||||
{
|
||||
public:
|
||||
@ -274,6 +276,9 @@ public:
|
||||
virtual bool createSelfSigned(const CertificateOptions &opts, const PKeyContext &priv) = 0;
|
||||
virtual const CertContextProps *props() const = 0;
|
||||
virtual PKeyContext *subjectPublicKey() const = 0; // caller must delete
|
||||
|
||||
// ownership of items IS NOT passed
|
||||
virtual Validity validate(const QList<CertContext*> &trusted, const QList<CertContext*> &untrusted, const QList<CRLContext *> &crls, UsageMode u) const = 0;
|
||||
};
|
||||
|
||||
class CSRContext : public CertBase
|
||||
@ -297,22 +302,16 @@ public:
|
||||
virtual const CRLContextProps *props() const = 0;
|
||||
};
|
||||
|
||||
class StoreContext : public Provider::Context
|
||||
class CertCollectionContext : public Provider::Context
|
||||
{
|
||||
public:
|
||||
StoreContext(Provider *p) : Provider::Context(p, "store") {}
|
||||
CertCollectionContext(Provider *p) : Provider::Context(p, "certcollection") {}
|
||||
|
||||
virtual void addCertificate(const CertContext &cert, Store::TrustMode t) = 0;
|
||||
virtual void addCRL(const CRLContext &crl) = 0;
|
||||
virtual Validity validate(const CertContext &cert, Store::UsageMode u) const = 0;
|
||||
virtual QList<CertContext*> certificates() const = 0; // caller must delete
|
||||
virtual QList<CRLContext*> crls() const = 0; // caller must delete
|
||||
virtual void append(const StoreContext &s) = 0;
|
||||
// ownership of items IS NOT passed
|
||||
virtual QByteArray toPKCS7(const QList<CertContext*> &certs, const QList<CRLContext*> &crls) const = 0;
|
||||
|
||||
// import / export
|
||||
virtual bool canUsePKCS7() const = 0;
|
||||
virtual QByteArray toPKCS7() const = 0;
|
||||
virtual ConvertResult fromPKCS7(const QByteArray &a, Store::TrustMode t) = 0;
|
||||
// ownership of items IS passed
|
||||
virtual ConvertResult fromPKCS7(const QByteArray &a, QList<CertContext*> *certs, QList<CRLContext*> *crls) const = 0;
|
||||
};
|
||||
|
||||
class CAContext : public Provider::Context
|
||||
@ -341,6 +340,18 @@ public:
|
||||
virtual ConvertResult fromPKCS12(const QByteArray &in, const QSecureArray &passphrase, QString *name, QList<CertContext*> *chain, PKeyContext **priv) const = 0;
|
||||
};
|
||||
|
||||
class KeyStoreContext : public Provider::Context
|
||||
{
|
||||
public:
|
||||
KeyStoreContext(Provider *p) : Provider::Context(p, "keystore") {}
|
||||
};
|
||||
|
||||
class KeyStoreListContext : public Provider::Context
|
||||
{
|
||||
public:
|
||||
KeyStoreListContext(Provider *p) : Provider::Context(p, "keystorelist") {}
|
||||
};
|
||||
|
||||
class TLSContext : public Provider::Context
|
||||
{
|
||||
public:
|
||||
@ -348,8 +359,8 @@ public:
|
||||
TLSContext(Provider *p) : Provider::Context(p, "tls") {}
|
||||
|
||||
virtual void reset() = 0;
|
||||
virtual bool startClient(const StoreContext &store, const CertContext &cert, const PKeyContext &key) = 0;
|
||||
virtual bool startServer(const StoreContext &store, const CertContext &cert, const PKeyContext &key) = 0;
|
||||
virtual bool startClient(const QList<CertContext*> &trusted, const QList<CRLContext*> &crls, const CertContext &cert, const PKeyContext &key) = 0;
|
||||
virtual bool startServer(const QList<CertContext*> &trusted, const QList<CRLContext*> &crls, const CertContext &cert, const PKeyContext &key) = 0;
|
||||
|
||||
virtual int handshake(const QByteArray &in, QByteArray *out) = 0;
|
||||
virtual int shutdown(const QByteArray &in, QByteArray *out) = 0;
|
||||
|
@ -2723,6 +2723,9 @@ public:
|
||||
return kc;
|
||||
}
|
||||
|
||||
// implemented later because it depends on MyCRLContext
|
||||
virtual QCA::Validity validate(const QList<QCA::CertContext*> &trusted, const QList<QCA::CertContext*> &untrusted, const QList<QCA::CRLContext *> &crls, QCA::UsageMode u) const;
|
||||
|
||||
void make_props()
|
||||
{
|
||||
X509 *x = item.cert;
|
||||
@ -3074,10 +3077,88 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static bool usage_check(const MyCertContext &cc, QCA::UsageMode u)
|
||||
{
|
||||
// TODO: check usage
|
||||
Q_UNUSED(cc);
|
||||
Q_UNUSED(u);
|
||||
return true;
|
||||
}
|
||||
|
||||
QCA::Validity MyCertContext::validate(const QList<QCA::CertContext*> &trusted, const QList<QCA::CertContext*> &untrusted, const QList<QCA::CRLContext *> &crls, QCA::UsageMode u) const
|
||||
{
|
||||
STACK_OF(X509) *trusted_list = sk_X509_new_null();
|
||||
STACK_OF(X509) *untrusted_list = sk_X509_new_null();
|
||||
QList<X509_CRL*> crl_list;
|
||||
|
||||
int n;
|
||||
for(n = 0; n < trusted.count(); ++n)
|
||||
{
|
||||
const MyCertContext *cc = static_cast<const MyCertContext *>(trusted[n]);
|
||||
X509 *x = cc->item.cert;
|
||||
CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
|
||||
sk_X509_push(trusted_list, x);
|
||||
}
|
||||
for(n = 0; n < untrusted.count(); ++n)
|
||||
{
|
||||
const MyCertContext *cc = static_cast<const MyCertContext *>(untrusted[n]);
|
||||
X509 *x = cc->item.cert;
|
||||
CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
|
||||
sk_X509_push(untrusted_list, x);
|
||||
}
|
||||
for(n = 0; n < crls.count(); ++n)
|
||||
{
|
||||
const MyCRLContext *cc = static_cast<const MyCRLContext *>(crls[n]);
|
||||
X509_CRL *x = cc->item.crl;
|
||||
CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
|
||||
crl_list.append(x);
|
||||
}
|
||||
|
||||
const MyCertContext *cc = this;
|
||||
X509 *x = cc->item.cert;
|
||||
|
||||
// verification happens through a store "context"
|
||||
X509_STORE_CTX *ctx = X509_STORE_CTX_new();
|
||||
|
||||
// make a store of crls
|
||||
X509_STORE *store = X509_STORE_new();
|
||||
for(int n = 0; n < crl_list.count(); ++n)
|
||||
X509_STORE_add_crl(store, crl_list[n]);
|
||||
|
||||
// the first initialization handles untrusted certs, crls, and target cert
|
||||
X509_STORE_CTX_init(ctx, store, x, untrusted_list);
|
||||
|
||||
// this initializes the trusted certs
|
||||
X509_STORE_CTX_trusted_stack(ctx, trusted_list);
|
||||
|
||||
// verify!
|
||||
int ret = X509_verify_cert(ctx);
|
||||
int err = -1;
|
||||
if(!ret)
|
||||
err = ctx->error;
|
||||
|
||||
// cleanup
|
||||
X509_STORE_CTX_free(ctx);
|
||||
X509_STORE_free(store);
|
||||
|
||||
sk_X509_pop_free(trusted_list, X509_free);
|
||||
sk_X509_pop_free(untrusted_list, X509_free);
|
||||
for(int n = 0; n < crl_list.count(); ++n)
|
||||
X509_CRL_free(crl_list[n]);
|
||||
|
||||
if(!ret)
|
||||
return convert_verify_error(err);
|
||||
|
||||
if(!usage_check(*cc, u))
|
||||
return QCA::ErrorInvalidPurpose;
|
||||
|
||||
return QCA::ValidityGood;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// MyStoreContext
|
||||
//----------------------------------------------------------------------------
|
||||
class MyStoreContext : public QCA::StoreContext
|
||||
/*class MyStoreContext : public QCA::StoreContext
|
||||
{
|
||||
public:
|
||||
STACK_OF(X509) *trusted, *untrusted;
|
||||
@ -3282,7 +3363,7 @@ public:
|
||||
Q_UNUSED(u);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
||||
class opensslCipherContext : public QCA::CipherContext
|
||||
{
|
||||
@ -3547,8 +3628,8 @@ public:
|
||||
return new MyCSRContext( this );
|
||||
else if ( type == "crl" )
|
||||
return new MyCRLContext( this );
|
||||
else if ( type == "store" )
|
||||
return new MyStoreContext( this );
|
||||
//else if ( type == "store" )
|
||||
// return new MyStoreContext( this );
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
2
qca.pro
2
qca.pro
@ -36,6 +36,7 @@ PUBLIC_HEADERS += \
|
||||
$$QCA_INC/qca_basic.h \
|
||||
$$QCA_INC/qca_publickey.h \
|
||||
$$QCA_INC/qca_cert.h \
|
||||
$$QCA_INC/qca_keystore.h \
|
||||
$$QCA_INC/qca_securelayer.h \
|
||||
$$QCA_INC/qca_securemessage.h \
|
||||
$$QCA_INC/qcaprovider.h \
|
||||
@ -50,6 +51,7 @@ SOURCES += \
|
||||
$$QCA_CPP/qca_basic.cpp \
|
||||
$$QCA_CPP/qca_publickey.cpp \
|
||||
$$QCA_CPP/qca_cert.cpp \
|
||||
$$QCA_CPP/qca_keystore.cpp \
|
||||
$$QCA_CPP/qca_securelayer.cpp \
|
||||
$$QCA_CPP/qca_securemessage.cpp \
|
||||
$$QCA_CPP/qca_default.cpp
|
||||
|
404
src/qca_cert.cpp
404
src/qca_cert.cpp
@ -343,6 +343,36 @@ SignatureAlgorithm Certificate::signatureAlgorithm() const
|
||||
return static_cast<const CertContext *>(context())->props()->sigalgo;
|
||||
}
|
||||
|
||||
Validity Certificate::validate(const CertificateCollection &trusted, const CertificateCollection &untrusted, UsageMode u) const
|
||||
{
|
||||
QList<CertContext*> trusted_list;
|
||||
QList<CertContext*> untrusted_list;
|
||||
QList<CRLContext*> crl_list;
|
||||
|
||||
QList<Certificate> trusted_certs = trusted.certificates();
|
||||
QList<Certificate> untrusted_certs = untrusted.certificates();
|
||||
QList<CRL> crls = trusted.crls() + untrusted.crls();
|
||||
|
||||
int n;
|
||||
for(n = 0; n < trusted_certs.count(); ++n)
|
||||
{
|
||||
CertContext *c = static_cast<CertContext *>(trusted_certs[n].context());
|
||||
trusted_list += c;
|
||||
}
|
||||
for(n = 0; n < untrusted_certs.count(); ++n)
|
||||
{
|
||||
CertContext *c = static_cast<CertContext *>(untrusted_certs[n].context());
|
||||
untrusted_list += c;
|
||||
}
|
||||
for(n = 0; n < crls.count(); ++n)
|
||||
{
|
||||
CRLContext *c = static_cast<CRLContext *>(crls[n].context());
|
||||
crl_list += c;
|
||||
}
|
||||
|
||||
return static_cast<const CertContext *>(context())->validate(trusted_list, untrusted_list, crl_list, u);
|
||||
}
|
||||
|
||||
QSecureArray Certificate::toDER() const
|
||||
{
|
||||
return static_cast<const CertContext *>(context())->toDER();
|
||||
@ -717,11 +747,15 @@ CRL CRL::fromPEM(const QString &s, ConvertResult *result, const QString &provide
|
||||
//----------------------------------------------------------------------------
|
||||
// Store
|
||||
//----------------------------------------------------------------------------
|
||||
static QString readNextPem(QTextStream *ts)
|
||||
// TODO: support CRLs
|
||||
// CRL / X509 CRL
|
||||
// CERTIFICATE / X509 CERTIFICATE
|
||||
static QString readNextPem(QTextStream *ts, bool *isCRL)
|
||||
{
|
||||
QString pem;
|
||||
bool found = false;
|
||||
bool done = false;
|
||||
*isCRL = false;
|
||||
while(!ts->atEnd())
|
||||
{
|
||||
QString line = ts->readLine();
|
||||
@ -748,139 +782,190 @@ static QString readNextPem(QTextStream *ts)
|
||||
return pem;
|
||||
}
|
||||
|
||||
Store::Store(const QString &provider)
|
||||
:Algorithm("store", provider)
|
||||
class CertificateCollection::Private : public QSharedData
|
||||
{
|
||||
public:
|
||||
QList<Certificate> certs;
|
||||
QList<CRL> crls;
|
||||
};
|
||||
|
||||
CertificateCollection::CertificateCollection()
|
||||
:d(new Private)
|
||||
{
|
||||
}
|
||||
|
||||
void Store::addCertificate(const Certificate &cert, TrustMode t)
|
||||
CertificateCollection::CertificateCollection(const CertificateCollection &from)
|
||||
:d(from.d)
|
||||
{
|
||||
static_cast<StoreContext *>(context())->addCertificate(*(static_cast<const CertContext *>(cert.context())), t);
|
||||
}
|
||||
|
||||
void Store::addCRL(const CRL &crl)
|
||||
CertificateCollection::~CertificateCollection()
|
||||
{
|
||||
static_cast<StoreContext *>(context())->addCRL(*(static_cast<const CRLContext *>(crl.context())));
|
||||
}
|
||||
|
||||
Validity Store::validate(const Certificate &cert, UsageMode u) const
|
||||
CertificateCollection & CertificateCollection::operator=(const CertificateCollection &from)
|
||||
{
|
||||
return static_cast<const StoreContext *>(context())->validate(*(static_cast<const CertContext *>(cert.context())), u);
|
||||
d = from.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QList<Certificate> Store::certificates() const
|
||||
void CertificateCollection::addCertificate(const Certificate &cert)
|
||||
{
|
||||
QList<CertContext *> in = static_cast<const StoreContext *>(context())->certificates();
|
||||
QList<Certificate> out;
|
||||
for(int n = 0; n < in.count(); ++n)
|
||||
{
|
||||
Certificate cert;
|
||||
cert.change(in[n]);
|
||||
out.append(cert);
|
||||
}
|
||||
return out;
|
||||
d->certs.append(cert);
|
||||
}
|
||||
|
||||
QList<CRL> Store::crls() const
|
||||
void CertificateCollection::addCRL(const CRL &crl)
|
||||
{
|
||||
QList<CRLContext *> in = static_cast<const StoreContext *>(context())->crls();
|
||||
QList<CRL> out;
|
||||
for(int n = 0; n < in.count(); ++n)
|
||||
{
|
||||
CRL crl;
|
||||
crl.change(in[n]);
|
||||
out.append(crl);
|
||||
}
|
||||
return out;
|
||||
d->crls.append(crl);
|
||||
}
|
||||
|
||||
bool Store::canUsePKCS7(const QString &provider)
|
||||
QList<Certificate> CertificateCollection::certificates() const
|
||||
{
|
||||
StoreContext *c = static_cast<StoreContext *>(getContext("store", provider));
|
||||
bool ok = c->canUsePKCS7();
|
||||
return d->certs;
|
||||
}
|
||||
|
||||
QList<CRL> CertificateCollection::crls() const
|
||||
{
|
||||
return d->crls;
|
||||
}
|
||||
|
||||
void CertificateCollection::append(const CertificateCollection &other)
|
||||
{
|
||||
d->certs += other.d->certs;
|
||||
d->crls += other.d->crls;
|
||||
}
|
||||
|
||||
CertificateCollection CertificateCollection::operator+(const CertificateCollection &other) const
|
||||
{
|
||||
CertificateCollection c = *this;
|
||||
c.append(other);
|
||||
return c;
|
||||
}
|
||||
|
||||
CertificateCollection & CertificateCollection::operator+=(const CertificateCollection &other)
|
||||
{
|
||||
append(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CertificateCollection::canUsePKCS7(const QString &provider)
|
||||
{
|
||||
CertCollectionContext *c = static_cast<CertCollectionContext *>(getContext("certcollection", provider));
|
||||
bool ok = c ? true : false;
|
||||
delete c;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Store::toPKCS7File(const QString &fileName) const
|
||||
{
|
||||
return arrayToFile(fileName, static_cast<const StoreContext *>(context())->toPKCS7());
|
||||
}
|
||||
|
||||
bool Store::toFlatTextFile(const QString &fileName) const
|
||||
bool CertificateCollection::toFlatTextFile(const QString &fileName)
|
||||
{
|
||||
QFile f(fileName);
|
||||
if(!f.open(QFile::WriteOnly))
|
||||
return false;
|
||||
|
||||
QList<CertContext *> in = static_cast<const StoreContext *>(context())->certificates();
|
||||
QTextStream ts(&f);
|
||||
for(int n = 0; n < in.count(); ++n)
|
||||
ts << in[n]->toPEM();
|
||||
qDeleteAll(in);
|
||||
int n;
|
||||
for(n = 0; n < d->certs.count(); ++n)
|
||||
ts << d->certs[n].toPEM();
|
||||
for(n = 0; n < d->crls.count(); ++n)
|
||||
ts << d->crls[n].toPEM();
|
||||
return true;
|
||||
}
|
||||
|
||||
Store Store::fromPKCS7File(const QString &fileName, TrustMode t, ConvertResult *result, const QString &provider)
|
||||
bool CertificateCollection::toPKCS7File(const QString &fileName, const QString &provider)
|
||||
{
|
||||
QByteArray der;
|
||||
if(!arrayFromFile(fileName, &der))
|
||||
CertCollectionContext *col = static_cast<CertCollectionContext *>(getContext("certcollection", provider));
|
||||
|
||||
QList<CertContext*> cert_list;
|
||||
QList<CRLContext*> crl_list;
|
||||
int n;
|
||||
for(n = 0; n < d->certs.count(); ++n)
|
||||
{
|
||||
if(result)
|
||||
*result = ErrorFile;
|
||||
return Store();
|
||||
CertContext *c = static_cast<CertContext *>(d->certs[n].context());
|
||||
cert_list += c;
|
||||
}
|
||||
for(n = 0; n < d->crls.count(); ++n)
|
||||
{
|
||||
CRLContext *c = static_cast<CRLContext *>(d->crls[n].context());
|
||||
crl_list += c;
|
||||
}
|
||||
|
||||
Store store;
|
||||
StoreContext *c = static_cast<StoreContext *>(getContext("store", provider));
|
||||
ConvertResult r = c->fromPKCS7(der, t);
|
||||
if(result)
|
||||
*result = r;
|
||||
if(r == ConvertGood)
|
||||
store.change(c);
|
||||
return store;
|
||||
QByteArray result = col->toPKCS7(cert_list, crl_list);
|
||||
delete col;
|
||||
|
||||
return arrayToFile(fileName, result);
|
||||
}
|
||||
|
||||
Store Store::fromFlatTextFile(const QString &fileName, TrustMode t, ConvertResult *result, const QString &provider)
|
||||
CertificateCollection CertificateCollection::fromFlatTextFile(const QString &fileName, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
QFile f(fileName);
|
||||
if(!f.open(QFile::ReadOnly))
|
||||
{
|
||||
if(result)
|
||||
*result = ErrorFile;
|
||||
return Store();
|
||||
return CertificateCollection();
|
||||
}
|
||||
|
||||
Store store(provider);
|
||||
CertificateCollection certs;
|
||||
QTextStream ts(&f);
|
||||
while(1)
|
||||
{
|
||||
QString pem = readNextPem(&ts);
|
||||
bool isCRL;
|
||||
QString pem = readNextPem(&ts, &isCRL);
|
||||
if(pem.isNull())
|
||||
break;
|
||||
Certificate cert = Certificate::fromPEM(pem, 0, store.provider()->name());
|
||||
if(!cert.isNull())
|
||||
store.addCertificate(cert, t);
|
||||
if(isCRL)
|
||||
{
|
||||
CRL c = CRL::fromPEM(pem, 0, provider);
|
||||
if(!c.isNull())
|
||||
certs.addCRL(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
Certificate c = Certificate::fromPEM(pem, 0, provider);
|
||||
if(!c.isNull())
|
||||
certs.addCertificate(c);
|
||||
}
|
||||
}
|
||||
return store;
|
||||
return certs;
|
||||
}
|
||||
|
||||
void Store::append(const Store &a)
|
||||
CertificateCollection CertificateCollection::fromPKCS7File(const QString &fileName, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
static_cast<StoreContext *>(context())->append(*(static_cast<const StoreContext *>(a.context())));
|
||||
}
|
||||
QByteArray der;
|
||||
if(!arrayFromFile(fileName, &der))
|
||||
{
|
||||
if(result)
|
||||
*result = ErrorFile;
|
||||
return CertificateCollection();
|
||||
}
|
||||
|
||||
Store Store::operator+(const Store &a) const
|
||||
{
|
||||
Store s = *this;
|
||||
s.append(a);
|
||||
return s;
|
||||
}
|
||||
CertificateCollection certs;
|
||||
|
||||
Store & Store::operator+=(const Store &a)
|
||||
{
|
||||
append(a);
|
||||
return *this;
|
||||
QList<CertContext*> cert_list;
|
||||
QList<CRLContext*> crl_list;
|
||||
CertCollectionContext *col = static_cast<CertCollectionContext *>(getContext("certcollection", provider));
|
||||
ConvertResult r = col->fromPKCS7(der, &cert_list, &crl_list);
|
||||
delete col;
|
||||
|
||||
if(result)
|
||||
*result = r;
|
||||
if(r == ConvertGood)
|
||||
{
|
||||
int n;
|
||||
for(n = 0; n < cert_list.count(); ++n)
|
||||
{
|
||||
Certificate c;
|
||||
c.change(cert_list[n]);
|
||||
certs.addCertificate(c);
|
||||
}
|
||||
for(n = 0; n < crl_list.count(); ++n)
|
||||
{
|
||||
CRL c;
|
||||
c.change(crl_list[n]);
|
||||
certs.addCRL(c);
|
||||
}
|
||||
}
|
||||
return certs;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -927,9 +1012,9 @@ CRL CertificateAuthority::updateCRL(const CRL &crl, const QList<CRLEntry> &entri
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// PersonalBundle
|
||||
// KeyBundle
|
||||
//----------------------------------------------------------------------------
|
||||
class PersonalBundle::Private
|
||||
class KeyBundle::Private : public QSharedData
|
||||
{
|
||||
public:
|
||||
QString name;
|
||||
@ -937,65 +1022,64 @@ public:
|
||||
PrivateKey key;
|
||||
};
|
||||
|
||||
PersonalBundle::PersonalBundle()
|
||||
KeyBundle::KeyBundle()
|
||||
:d(new Private)
|
||||
{
|
||||
d = new Private;
|
||||
}
|
||||
|
||||
PersonalBundle::PersonalBundle(const QString &fileName, const QSecureArray &passphrase)
|
||||
KeyBundle::KeyBundle(const QString &fileName, const QSecureArray &passphrase)
|
||||
:d(new Private)
|
||||
{
|
||||
d = new Private;
|
||||
*this = fromFile(fileName, passphrase, 0, QString());
|
||||
}
|
||||
|
||||
PersonalBundle::PersonalBundle(const PersonalBundle &from)
|
||||
KeyBundle::KeyBundle(const KeyBundle &from)
|
||||
:d(from.d)
|
||||
{
|
||||
d = new Private(*from.d);
|
||||
}
|
||||
|
||||
PersonalBundle::~PersonalBundle()
|
||||
KeyBundle::~KeyBundle()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
PersonalBundle & PersonalBundle::operator=(const PersonalBundle &from)
|
||||
KeyBundle & KeyBundle::operator=(const KeyBundle &from)
|
||||
{
|
||||
*d = *from.d;
|
||||
d = from.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool PersonalBundle::isNull() const
|
||||
bool KeyBundle::isNull() const
|
||||
{
|
||||
return d->chain.isEmpty();
|
||||
}
|
||||
|
||||
QString PersonalBundle::name() const
|
||||
QString KeyBundle::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
CertificateChain PersonalBundle::certificateChain() const
|
||||
CertificateChain KeyBundle::certificateChain() const
|
||||
{
|
||||
return d->chain;
|
||||
}
|
||||
|
||||
PrivateKey PersonalBundle::privateKey() const
|
||||
PrivateKey KeyBundle::privateKey() const
|
||||
{
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void PersonalBundle::setName(const QString &s)
|
||||
void KeyBundle::setName(const QString &s)
|
||||
{
|
||||
d->name = s;
|
||||
}
|
||||
|
||||
void PersonalBundle::setCertificateChainAndKey(const CertificateChain &c, const PrivateKey &key)
|
||||
void KeyBundle::setCertificateChainAndKey(const CertificateChain &c, const PrivateKey &key)
|
||||
{
|
||||
d->chain = c;
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
QByteArray PersonalBundle::toArray(const QSecureArray &passphrase, const QString &provider) const
|
||||
QByteArray KeyBundle::toArray(const QSecureArray &passphrase, const QString &provider) const
|
||||
{
|
||||
PIXContext *pix = static_cast<PIXContext *>(getContext("pix", provider));
|
||||
|
||||
@ -1008,18 +1092,18 @@ QByteArray PersonalBundle::toArray(const QSecureArray &passphrase, const QString
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool PersonalBundle::toFile(const QString &fileName, const QSecureArray &passphrase, const QString &provider) const
|
||||
bool KeyBundle::toFile(const QString &fileName, const QSecureArray &passphrase, const QString &provider) const
|
||||
{
|
||||
return arrayToFile(fileName, toArray(passphrase, provider));
|
||||
}
|
||||
|
||||
PersonalBundle PersonalBundle::fromArray(const QByteArray &a, const QSecureArray &passphrase, ConvertResult *result, const QString &provider)
|
||||
KeyBundle KeyBundle::fromArray(const QByteArray &a, const QSecureArray &passphrase, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
QString name;
|
||||
QList<CertContext *> list;
|
||||
PKeyContext *kc = 0;
|
||||
|
||||
PersonalBundle bundle;
|
||||
KeyBundle bundle;
|
||||
PIXContext *pix = static_cast<PIXContext *>(getContext("pix", provider));
|
||||
ConvertResult r = pix->fromPKCS12(a, passphrase, &name, &list, &kc);
|
||||
if(result)
|
||||
@ -1038,16 +1122,134 @@ PersonalBundle PersonalBundle::fromArray(const QByteArray &a, const QSecureArray
|
||||
return bundle;
|
||||
}
|
||||
|
||||
PersonalBundle PersonalBundle::fromFile(const QString &fileName, const QSecureArray &passphrase, ConvertResult *result, const QString &provider)
|
||||
KeyBundle KeyBundle::fromFile(const QString &fileName, const QSecureArray &passphrase, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
QByteArray der;
|
||||
if(!arrayFromFile(fileName, &der))
|
||||
{
|
||||
if(result)
|
||||
*result = ErrorFile;
|
||||
return PersonalBundle();
|
||||
return KeyBundle();
|
||||
}
|
||||
return fromArray(der, passphrase, result, provider);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// PGPKey
|
||||
//----------------------------------------------------------------------------
|
||||
// TODO
|
||||
PGPKey::PGPKey()
|
||||
{
|
||||
}
|
||||
|
||||
PGPKey::PGPKey(const QString &fileName)
|
||||
{
|
||||
Q_UNUSED(fileName);
|
||||
}
|
||||
|
||||
PGPKey::PGPKey(const PGPKey &from)
|
||||
:Algorithm(from)
|
||||
{
|
||||
}
|
||||
|
||||
PGPKey::~PGPKey()
|
||||
{
|
||||
}
|
||||
|
||||
PGPKey & PGPKey::operator=(const PGPKey &from)
|
||||
{
|
||||
Algorithm::operator=(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool PGPKey::isNull() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString PGPKey::keyId() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString PGPKey::primaryUserId() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList PGPKey::userIds() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
bool PGPKey::havePrivate() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QDateTime PGPKey::creationDate() const
|
||||
{
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
QDateTime PGPKey::expirationDate() const
|
||||
{
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
QString PGPKey::fingerprint() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool PGPKey::inKeyring() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PGPKey::isTrusted() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QSecureArray PGPKey::toArray() const
|
||||
{
|
||||
return QSecureArray();
|
||||
}
|
||||
|
||||
QString PGPKey::toString() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool PGPKey::toFile(const QString &fileName) const
|
||||
{
|
||||
Q_UNUSED(fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
PGPKey PGPKey::fromArray(const QSecureArray &a, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
Q_UNUSED(a);
|
||||
Q_UNUSED(result);
|
||||
Q_UNUSED(provider);
|
||||
return PGPKey();
|
||||
}
|
||||
|
||||
PGPKey PGPKey::fromString(const QString &s, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
Q_UNUSED(s);
|
||||
Q_UNUSED(result);
|
||||
Q_UNUSED(provider);
|
||||
return PGPKey();
|
||||
}
|
||||
|
||||
PGPKey PGPKey::fromFile(const QString &fileName, ConvertResult *result, const QString &provider)
|
||||
{
|
||||
Q_UNUSED(fileName);
|
||||
Q_UNUSED(result);
|
||||
Q_UNUSED(provider);
|
||||
return PGPKey();
|
||||
}
|
||||
|
||||
}
|
||||
|
168
src/qca_core.cpp
168
src/qca_core.cpp
@ -25,6 +25,7 @@
|
||||
#include "qca_plugin.h"
|
||||
#include "qca_textfilter.h"
|
||||
#include "qca_cert.h"
|
||||
#include "qca_keystore.h"
|
||||
#include "qcaprovider.h"
|
||||
|
||||
#ifndef QCA_NO_SYSTEMSTORE
|
||||
@ -43,12 +44,30 @@ Provider *create_default_provider();
|
||||
//----------------------------------------------------------------------------
|
||||
// Global
|
||||
//----------------------------------------------------------------------------
|
||||
static QMutex *manager_mutex = 0;
|
||||
static QString *app_name = 0;
|
||||
static QCA::ProviderManager *manager = 0;
|
||||
static QCA::Random *global_rng = 0;
|
||||
static bool qca_init = false;
|
||||
static bool qca_secmem = false;
|
||||
class Global
|
||||
{
|
||||
public:
|
||||
bool secmem;
|
||||
QString app_name;
|
||||
QMutex manager_mutex;
|
||||
ProviderManager manager;
|
||||
Random *rng;
|
||||
KeyStoreManager *ksm;
|
||||
|
||||
Global()
|
||||
{
|
||||
rng = 0;
|
||||
ksm = 0;
|
||||
secmem = false;
|
||||
}
|
||||
|
||||
~Global()
|
||||
{
|
||||
delete rng;
|
||||
}
|
||||
};
|
||||
|
||||
static Global *global = 0;
|
||||
|
||||
static bool features_have(const QStringList &have, const QStringList &want)
|
||||
{
|
||||
@ -62,7 +81,7 @@ static bool features_have(const QStringList &have, const QStringList &want)
|
||||
|
||||
void init()
|
||||
{
|
||||
if(qca_init)
|
||||
if(global)
|
||||
return;
|
||||
|
||||
init(Practical, 64);
|
||||
@ -70,11 +89,9 @@ void init()
|
||||
|
||||
void init(MemoryMode mode, int prealloc)
|
||||
{
|
||||
if(qca_init)
|
||||
if(global)
|
||||
return;
|
||||
|
||||
qca_init = true;
|
||||
|
||||
bool allow_mmap_fallback = false;
|
||||
bool drop_root = false;
|
||||
if(mode == Practical)
|
||||
@ -85,7 +102,7 @@ void init(MemoryMode mode, int prealloc)
|
||||
else if(mode == Locking)
|
||||
drop_root = true;
|
||||
|
||||
qca_secmem = botan_init(prealloc, allow_mmap_fallback);
|
||||
bool secmem = botan_init(prealloc, allow_mmap_fallback);
|
||||
|
||||
if(drop_root)
|
||||
{
|
||||
@ -94,55 +111,43 @@ void init(MemoryMode mode, int prealloc)
|
||||
#endif
|
||||
}
|
||||
|
||||
manager_mutex = new QMutex;
|
||||
|
||||
manager = new ProviderManager;
|
||||
manager->setDefault(create_default_provider()); // manager owns it
|
||||
|
||||
app_name = new QString;
|
||||
global = new Global;
|
||||
global->secmem = secmem;
|
||||
global->manager.setDefault(create_default_provider()); // manager owns it
|
||||
}
|
||||
|
||||
void deinit()
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return;
|
||||
|
||||
delete global_rng;
|
||||
global_rng = 0;
|
||||
|
||||
delete app_name;
|
||||
app_name = 0;
|
||||
|
||||
delete manager;
|
||||
manager = 0;
|
||||
|
||||
delete manager_mutex;
|
||||
manager_mutex = 0;
|
||||
|
||||
delete global;
|
||||
global = 0;
|
||||
botan_deinit();
|
||||
qca_secmem = false;
|
||||
qca_init = false;
|
||||
}
|
||||
|
||||
bool haveSecureMemory()
|
||||
{
|
||||
return qca_secmem;
|
||||
if(!global)
|
||||
return false;
|
||||
|
||||
return global->secmem;
|
||||
}
|
||||
|
||||
bool isSupported(const QStringList &features)
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return false;
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
if(features_have(manager->allFeatures(), features))
|
||||
if(features_have(global->manager.allFeatures(), features))
|
||||
return true;
|
||||
|
||||
// ok, try scanning for new stuff
|
||||
manager->scan();
|
||||
global->manager.scan();
|
||||
|
||||
if(features_have(manager->allFeatures(), features))
|
||||
if(features_have(global->manager.allFeatures(), features))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -157,95 +162,100 @@ QStringList supportedFeatures()
|
||||
{
|
||||
init();
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
// query all features
|
||||
manager->scan();
|
||||
return manager->allFeatures();
|
||||
global->manager.scan();
|
||||
return global->manager.allFeatures();
|
||||
}
|
||||
|
||||
QStringList defaultFeatures()
|
||||
{
|
||||
init();
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
return manager->find("default")->features();
|
||||
return global->manager.find("default")->features();
|
||||
}
|
||||
|
||||
bool insertProvider(Provider *p, int priority)
|
||||
{
|
||||
init();
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
return manager->add(p, priority);
|
||||
return global->manager.add(p, priority);
|
||||
}
|
||||
|
||||
void setProviderPriority(const QString &name, int priority)
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return;
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
manager->changePriority(name, priority);
|
||||
global->manager.changePriority(name, priority);
|
||||
}
|
||||
|
||||
int providerPriority(const QString &name)
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return -1;
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
return manager->getPriority(name);
|
||||
return global->manager.getPriority(name);
|
||||
}
|
||||
|
||||
const ProviderList & providers()
|
||||
{
|
||||
init();
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
return manager->providers();
|
||||
return global->manager.providers();
|
||||
}
|
||||
|
||||
void scanForPlugins()
|
||||
{
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
manager->scan();
|
||||
global->manager.scan();
|
||||
}
|
||||
|
||||
void unloadAllPlugins()
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return;
|
||||
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
// if the global_rng was owned by a plugin, then delete it
|
||||
if(global_rng && (global_rng->provider() != manager->find("default")))
|
||||
if(global->rng && (global->rng->provider() != global->manager.find("default")))
|
||||
{
|
||||
delete global_rng;
|
||||
global_rng = 0;
|
||||
delete global->rng;
|
||||
global->rng = 0;
|
||||
}
|
||||
|
||||
manager->unloadAll();
|
||||
global->manager.unloadAll();
|
||||
}
|
||||
|
||||
Random & globalRNG()
|
||||
{
|
||||
if(!global_rng)
|
||||
global_rng = new Random;
|
||||
return *global_rng;
|
||||
if(!global->rng)
|
||||
global->rng = new Random;
|
||||
return *global->rng;
|
||||
}
|
||||
|
||||
void setGlobalRNG(const QString &provider)
|
||||
{
|
||||
delete global_rng;
|
||||
global_rng = new Random(provider);
|
||||
delete global->rng;
|
||||
global->rng = new Random(provider);
|
||||
}
|
||||
|
||||
KeyStoreManager *keyStoreManager()
|
||||
{
|
||||
return global->ksm;
|
||||
}
|
||||
|
||||
bool haveSystemStore()
|
||||
@ -257,27 +267,27 @@ bool haveSystemStore()
|
||||
#endif
|
||||
}
|
||||
|
||||
Store systemStore(const QString &provider)
|
||||
CertificateCollection systemStore(const QString &provider)
|
||||
{
|
||||
#ifndef QCA_NO_SYSTEMSTORE
|
||||
return qca_get_systemstore(provider);
|
||||
#else
|
||||
return Store(provider);
|
||||
return CertificateCollection();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString appName()
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return QString();
|
||||
return *app_name;
|
||||
return global->app_name;
|
||||
}
|
||||
|
||||
void setAppName(const QString &s)
|
||||
{
|
||||
if(!qca_init)
|
||||
if(!global)
|
||||
return;
|
||||
*app_name = s;
|
||||
global->app_name = s;
|
||||
}
|
||||
|
||||
QString arrayToHex(const QSecureArray &a)
|
||||
@ -292,33 +302,33 @@ QByteArray hexToArray(const QString &str)
|
||||
|
||||
static Provider *getProviderForType(const QString &type, const QString &provider)
|
||||
{
|
||||
QMutexLocker lock(manager_mutex);
|
||||
QMutexLocker lock(&global->manager_mutex);
|
||||
|
||||
Provider *p = 0;
|
||||
bool scanned = false;
|
||||
if(!provider.isEmpty())
|
||||
{
|
||||
// try using specific provider
|
||||
p = manager->findFor(provider, type);
|
||||
p = global->manager.findFor(provider, type);
|
||||
if(!p)
|
||||
{
|
||||
// maybe this provider is new, so scan and try again
|
||||
manager->scan();
|
||||
global->manager.scan();
|
||||
scanned = true;
|
||||
p = manager->findFor(provider, type);
|
||||
p = global->manager.findFor(provider, type);
|
||||
}
|
||||
}
|
||||
if(!p)
|
||||
{
|
||||
// try using some other provider
|
||||
p = manager->findFor(QString(), type);
|
||||
p = global->manager.findFor(QString(), type);
|
||||
if((!p || p->name() == "default") && !scanned)
|
||||
{
|
||||
// maybe there are new providers, so scan and try again
|
||||
// before giving up or using default
|
||||
manager->scan();
|
||||
global->manager.scan();
|
||||
scanned = true;
|
||||
p = manager->findFor(QString::null, type);
|
||||
p = global->manager.findFor(QString(), type);
|
||||
}
|
||||
}
|
||||
|
||||
|
217
src/qca_keystore.cpp
Normal file
217
src/qca_keystore.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* qca_keystore.cpp - Qt Cryptographic Architecture
|
||||
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
|
||||
* Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qca_keystore.h"
|
||||
|
||||
namespace QCA {
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// KeyStoreEntry
|
||||
//----------------------------------------------------------------------------
|
||||
KeyStoreEntry::KeyStoreEntry()
|
||||
{
|
||||
}
|
||||
|
||||
KeyStoreEntry::KeyStoreEntry(const KeyStoreEntry &from)
|
||||
:Algorithm(from)
|
||||
{
|
||||
}
|
||||
|
||||
KeyStoreEntry::~KeyStoreEntry()
|
||||
{
|
||||
}
|
||||
|
||||
KeyStoreEntry & KeyStoreEntry::operator=(const KeyStoreEntry &from)
|
||||
{
|
||||
Algorithm::operator=(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool KeyStoreEntry::isNull() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyStoreEntry::Type KeyStoreEntry::type() const
|
||||
{
|
||||
return TypeCertificate;
|
||||
}
|
||||
|
||||
QString KeyStoreEntry::name() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString KeyStoreEntry::id() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
KeyBundle KeyStoreEntry::keyBundle() const
|
||||
{
|
||||
return KeyBundle();
|
||||
}
|
||||
|
||||
Certificate KeyStoreEntry::certificate() const
|
||||
{
|
||||
return Certificate();
|
||||
}
|
||||
|
||||
CRL KeyStoreEntry::crl() const
|
||||
{
|
||||
return CRL();
|
||||
}
|
||||
|
||||
PGPKey KeyStoreEntry::pgpSecretKey() const
|
||||
{
|
||||
return PGPKey();
|
||||
}
|
||||
|
||||
PGPKey KeyStoreEntry::pgpPublicKey() const
|
||||
{
|
||||
return PGPKey();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// KeyStore
|
||||
//----------------------------------------------------------------------------
|
||||
KeyStore::KeyStore()
|
||||
{
|
||||
}
|
||||
|
||||
KeyStore::KeyStore(const KeyStore &from)
|
||||
:Algorithm(from)
|
||||
{
|
||||
}
|
||||
|
||||
KeyStore::~KeyStore()
|
||||
{
|
||||
}
|
||||
|
||||
KeyStore & KeyStore::operator=(const KeyStore &from)
|
||||
{
|
||||
Algorithm::operator=(from);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool KeyStore::isNull() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyStore::Type KeyStore::type() const
|
||||
{
|
||||
return System;
|
||||
}
|
||||
|
||||
QString KeyStore::name() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString KeyStore::id() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool KeyStore::isReadOnly() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<KeyStoreEntry> KeyStore::entryList() const
|
||||
{
|
||||
return QList<KeyStoreEntry>();
|
||||
}
|
||||
|
||||
bool KeyStore::containsTrustedCertificates() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyStore::containsIdentities() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyStore::containsPGPPublicKeys() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyStore::writeEntry(const KeyBundle &kb)
|
||||
{
|
||||
Q_UNUSED(kb);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyStore::writeEntry(const Certificate &cert)
|
||||
{
|
||||
Q_UNUSED(cert);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyStore::writeEntry(const CRL &crl)
|
||||
{
|
||||
Q_UNUSED(crl);
|
||||
return false;
|
||||
}
|
||||
|
||||
PGPKey KeyStore::writeEntry(const PGPKey &key)
|
||||
{
|
||||
Q_UNUSED(key);
|
||||
return PGPKey();
|
||||
}
|
||||
|
||||
bool KeyStore::removeEntry(const QString &id)
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// KeyStoreManager
|
||||
//----------------------------------------------------------------------------
|
||||
KeyStoreManager::KeyStoreManager()
|
||||
{
|
||||
}
|
||||
|
||||
KeyStoreManager::~KeyStoreManager()
|
||||
{
|
||||
}
|
||||
|
||||
KeyStore KeyStoreManager::keyStore(const QString &id) const
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
return KeyStore();
|
||||
}
|
||||
|
||||
QList<KeyStore> KeyStoreManager::keyStores() const
|
||||
{
|
||||
return QList<KeyStore>();
|
||||
}
|
||||
|
||||
int KeyStoreManager::count() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -98,7 +98,7 @@ class TLS::Private
|
||||
public:
|
||||
Private()
|
||||
{
|
||||
store = 0;
|
||||
//store = 0;
|
||||
}
|
||||
|
||||
void reset()
|
||||
@ -137,7 +137,7 @@ public:
|
||||
|
||||
Certificate ourCert;
|
||||
PrivateKey ourKey;
|
||||
Store *store;
|
||||
//Store *store;
|
||||
};
|
||||
|
||||
TLS::TLS(QObject *parent, const QString &provider)
|
||||
@ -171,9 +171,10 @@ void TLS::setCertificate(const CertificateChain &cert, const PrivateKey &key)
|
||||
d->ourKey = key;
|
||||
}
|
||||
|
||||
void TLS::setStore(const Store &store)
|
||||
void TLS::setTrustedCertificates(const CertificateCollection &trusted)
|
||||
{
|
||||
d->store = new Store(store);
|
||||
Q_UNUSED(trusted);
|
||||
//d->store = new Store(store);
|
||||
}
|
||||
|
||||
void TLS::setConstraints(SecurityLevel s)
|
||||
@ -206,9 +207,9 @@ bool TLS::startClient(const QString &host)
|
||||
d->reset();
|
||||
d->host = host;
|
||||
|
||||
if(!d->c->startClient(*((StoreContext *)d->store->context()), *((CertContext *)d->ourCert.context()), *((PKeyContext *)d->ourKey.context())))
|
||||
/*if(!d->c->startClient(*((StoreContext *)d->store->context()), *((CertContext *)d->ourCert.context()), *((PKeyContext *)d->ourKey.context())))
|
||||
return false;
|
||||
QTimer::singleShot(0, this, SLOT(update()));
|
||||
QTimer::singleShot(0, this, SLOT(update()));*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -216,9 +217,9 @@ bool TLS::startServer()
|
||||
{
|
||||
d->reset();
|
||||
|
||||
if(!d->c->startServer(*((StoreContext *)d->store->context()), *((CertContext *)d->ourCert.context()), *((PKeyContext *)d->ourKey.context())))
|
||||
/*if(!d->c->startServer(*((StoreContext *)d->store->context()), *((CertContext *)d->ourCert.context()), *((PKeyContext *)d->ourKey.context())))
|
||||
return false;
|
||||
QTimer::singleShot(0, this, SLOT(update()));
|
||||
QTimer::singleShot(0, this, SLOT(update()));*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -340,9 +340,9 @@ SMIME::~SMIME()
|
||||
{
|
||||
}
|
||||
|
||||
void SMIME::setStore(const Store &store)
|
||||
void SMIME::setTrustedCertificates(const CertificateCollection &trusted)
|
||||
{
|
||||
Q_UNUSED(store);
|
||||
Q_UNUSED(trusted);
|
||||
}
|
||||
|
||||
void SMIME::setPrivateKeys(const QList<PrivateKey> &keys)
|
||||
|
@ -28,7 +28,7 @@
|
||||
namespace QCA
|
||||
{
|
||||
bool qca_have_systemstore();
|
||||
Store qca_get_systemstore(const QString &provider);
|
||||
CertificateCollection qca_get_systemstore(const QString &provider);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -34,12 +34,12 @@ bool qca_have_systemstore()
|
||||
#endif
|
||||
}
|
||||
|
||||
Store qca_get_systemstore(const QString &provider)
|
||||
CertificateCollection qca_get_systemstore(const QString &provider)
|
||||
{
|
||||
#ifndef QCA_NO_SYSTEMSTORE
|
||||
return Store::fromFlatTextFile(QCA_SYSTEMSTORE_PATH, Store::Trusted, 0, provider);
|
||||
return CertificateCollection::fromFlatTextFile(QCA_SYSTEMSTORE_PATH, 0, provider);
|
||||
#else
|
||||
return Store(provider);
|
||||
return CertificateCollection();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ static void usage()
|
||||
printf(" --makereq [priv.pem] (passphrase)\n");
|
||||
printf(" --showcert [cert.pem]\n");
|
||||
printf(" --showreq [certreq.pem]\n");
|
||||
printf(" --validate [cert.pem] (nonrootstore.pem)\n");
|
||||
printf(" --validate [cert.pem] (nonroots.pem)\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@ -968,13 +968,14 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
// get roots
|
||||
QCA::Store store = QCA::systemStore();
|
||||
QCA::CertificateCollection roots = QCA::systemStore();
|
||||
|
||||
// get nonroots
|
||||
QCA::CertificateCollection nonroots;
|
||||
if(args.count() >= 3)
|
||||
store += QCA::Store::fromFlatTextFile(args[2]);
|
||||
nonroots = QCA::CertificateCollection::fromFlatTextFile(args[2]);
|
||||
|
||||
QCA::Validity v = store.validate(target);
|
||||
QCA::Validity v = target.validate(roots, nonroots);
|
||||
if(v == QCA::ValidityGood)
|
||||
printf("Certificate is valid\n");
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user