/* * Copyright (C) 2007 Justin Karneges * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * */ #include #include using namespace QCA; //---------------------------------------------------------------------------- // TestProvider //---------------------------------------------------------------------------- class TestProvider : public Provider { public: TestProvider() { } void init() { } void deinit() { } ~TestProvider() { } int version() const { return 0x010203; // 1.2.3 } int qcaVersion() const { return QCA_VERSION; } QString name() const { return "qca-test"; } QStringList features() const { QStringList list; list += "keystorelist"; return list; } Context *createContext(const QString &type); }; //---------------------------------------------------------------------------- // TestRSAContext //---------------------------------------------------------------------------- class TestRSAContext : public RSAContext { Q_OBJECT public: TestRSAContext(Provider *p) : RSAContext(p) { } Context *clone() const { return new TestRSAContext(*this); } virtual bool isNull() const { return false; } virtual PKey::Type type() const { return PKey::RSA; } virtual bool isPrivate() const { return false; } virtual bool canExport() const { return false; } virtual void convertToPublic() { } virtual int bits() const { return 2048; } virtual void createPrivate(int bits, int exp, bool block) { Q_UNUSED(bits); Q_UNUSED(exp); Q_UNUSED(block); } virtual void createPrivate(const BigInteger &n, const BigInteger &e, const BigInteger &p, const BigInteger &q, const BigInteger &d) { Q_UNUSED(n); Q_UNUSED(e); Q_UNUSED(p); Q_UNUSED(q); Q_UNUSED(d); } virtual void createPublic(const BigInteger &n, const BigInteger &e) { Q_UNUSED(n); Q_UNUSED(e); } virtual BigInteger n() const { return BigInteger(); } virtual BigInteger e() const { return BigInteger(); } virtual BigInteger p() const { return BigInteger(); } virtual BigInteger q() const { return BigInteger(); } virtual BigInteger d() const { return BigInteger(); } }; //---------------------------------------------------------------------------- // TestPKeyContext //---------------------------------------------------------------------------- class TestPKeyContext : public PKeyContext { Q_OBJECT public: TestRSAContext *_key; TestPKeyContext(Provider *p) : PKeyContext(p), _key(0) { } ~TestPKeyContext() { delete _key; } Context *clone() const { return new TestPKeyContext(*this); } virtual QList supportedTypes() const { QList list; list += PKey::RSA; return list; } virtual QList supportedIOTypes() const { return QList(); } virtual QList supportedPBEAlgorithms() const { return QList(); } virtual PKeyBase *key() { return _key; } virtual const PKeyBase *key() const { return _key; } virtual void setKey(PKeyBase *key) { delete _key; _key = (TestRSAContext *)key; } virtual bool importKey(const PKeyBase *key) { Q_UNUSED(key); return false; } }; //---------------------------------------------------------------------------- // TestCertContext //---------------------------------------------------------------------------- class TestCertContext : public CertContext { Q_OBJECT public: CertContextProps _props; TestCertContext(Provider *p) : CertContext(p) { } Context *clone() const { return new TestCertContext(*this); } virtual QByteArray toDER() const { return QByteArray(); } virtual QString toPEM() const { return QString(); } virtual ConvertResult fromDER(const QByteArray &a) { Q_UNUSED(a); return ErrorDecode; } virtual ConvertResult fromPEM(const QString &s) { Q_UNUSED(s); return ErrorDecode; } virtual bool createSelfSigned(const CertificateOptions &opts, const PKeyContext &priv) { Q_UNUSED(opts); Q_UNUSED(priv); return false; } virtual const CertContextProps *props() const { return &_props; } virtual bool compare(const CertContext *other) const { Q_UNUSED(other); return false; } virtual PKeyContext *subjectPublicKey() const { TestPKeyContext *kc = new TestPKeyContext(provider()); kc->setKey(new TestRSAContext(provider())); return kc; } virtual bool isIssuerOf(const CertContext *other) const { Q_UNUSED(other); return false; } virtual Validity validate(const QList &trusted, const QList &untrusted, const QList &crls, UsageMode u) const { Q_UNUSED(trusted); Q_UNUSED(untrusted); Q_UNUSED(crls); Q_UNUSED(u); return ErrorValidityUnknown; } virtual Validity validate_chain(const QList &chain, const QList &trusted, const QList &crls, UsageMode u) const { Q_UNUSED(chain); Q_UNUSED(trusted); Q_UNUSED(crls); Q_UNUSED(u); return ErrorValidityUnknown; } }; //---------------------------------------------------------------------------- // TestKeyStoreEntryContext //---------------------------------------------------------------------------- class TestKeyStoreEntryContext : public KeyStoreEntryContext { Q_OBJECT public: QString _id, _name, _storeId, _storeName; KeyBundle kb; bool avail; TestKeyStoreEntryContext(Provider *p) : KeyStoreEntryContext(p) { } virtual Context *clone() const { return new TestKeyStoreEntryContext(*this); } virtual KeyStoreEntry::Type type() const { return KeyStoreEntry::TypeKeyBundle; } virtual QString id() const { return _id; } virtual QString name() const { return _name; } virtual QString storeId() const { return _storeId; } virtual QString storeName() const { return _storeName; } virtual bool isAvailable() const { return avail; } virtual QString serialize() const { return QString(); } virtual KeyBundle keyBundle() const { return kb; } virtual bool ensureAccess() { return true; } }; //---------------------------------------------------------------------------- // TestData //---------------------------------------------------------------------------- class TestKeyStore { public: int contextId; KeyStore::Type type; QString storeId; QString name; bool readOnly; bool avail; QList certs; TestKeyStore() : contextId(-1), type(KeyStore::SmartCard), readOnly(true), avail(true) { } }; class TestData { public: int context_at; QList stores; TestData() : context_at(0) { } }; //---------------------------------------------------------------------------- // TestKeyStoreListContext //---------------------------------------------------------------------------- class TestKeyStoreListContext : public KeyStoreListContext { Q_OBJECT public: TestData data; int step; QTimer t; TestKeyStoreListContext(Provider *p) : KeyStoreListContext(p), t(this) { step = 0; KeyBundle cert1; Certificate pub1; TestCertContext *cc1 = new TestCertContext(provider()); cc1->_props.subject += CertificateInfoPair(CertificateInfoType(CommonName), "Test Cert 1"); pub1.change(cc1); PrivateKey sec1; sec1.change(new TestPKeyContext(provider())); cert1.setCertificateChainAndKey(pub1, sec1); TestKeyStore ks1; ks1.storeId = "store1"; ks1.name = "Test Store 1"; ks1.certs += cert1; data.stores += ks1; TestKeyStore ks2; ks2.storeId = "store2"; ks2.name = "Test Store 2"; ks2.readOnly = false; data.stores += ks2; connect(&t, SIGNAL(timeout()), SLOT(do_step())); } int findStore(int contextId) const { for(int n = 0; n < data.stores.count(); ++n) { if(data.stores[n].contextId == contextId) return n; } return -1; } virtual Context *clone() const { return 0; } virtual void start() { t.start(2000); } virtual void setUpdatesEnabled(bool enabled) { Q_UNUSED(enabled); } virtual QList keyStores() { QList list; for(int n = 0; n < data.stores.count(); ++n) { int id = data.stores[n].contextId; if(id != -1) list += id; } return list; } virtual KeyStore::Type type(int id) const { int at = findStore(id); if(at == -1) return KeyStore::SmartCard; return data.stores[at].type; } virtual QString storeId(int id) const { int at = findStore(id); if(at == -1) return QString(); return data.stores[at].storeId; } virtual QString name(int id) const { int at = findStore(id); if(at == -1) return QString(); return data.stores[at].name; } virtual bool isReadOnly(int id) const { int at = findStore(id); if(at == -1) return true; return data.stores[at].readOnly; } virtual QList entryTypes(int id) const { Q_UNUSED(id); QList list; list += KeyStoreEntry::TypeKeyBundle; return list; } virtual QList entryList(int id) { QList out; int at = findStore(id); if(at == -1) return out; TestKeyStore &store = data.stores[at]; for(int n = 0; n < store.certs.count(); ++n) { TestKeyStoreEntryContext *kse = new TestKeyStoreEntryContext(provider()); kse->_id = QString::number(n); kse->_name = store.certs[n].certificateChain().primary().commonName(); kse->_storeId = store.storeId; kse->_storeName = store.name; kse->kb = store.certs[n]; kse->avail = store.avail; } return out; } virtual KeyStoreEntryContext *entryPassive(const QString &serialized) { Q_UNUSED(serialized); return 0; } virtual QString writeEntry(int id, const KeyBundle &kb) { int at = findStore(id); if(at == -1) return QString(); if(data.stores[at].readOnly) return QString(); data.stores[at].certs += kb; return QString::number(data.stores[at].certs.count() - 1); } virtual bool removeEntry(int id, const QString &entryId) { int at = findStore(id); if(at == -1) return false; if(data.stores[at].readOnly) return false; int index = entryId.toInt(); if(index < 0 || index >= data.stores[at].certs.count()) return false; data.stores[at].certs.removeAt(index); return true; } private slots: void do_step() { if(step == 0) { // make first store available data.stores[0].contextId = 1; emit busyEnd(); } else if(step == 1) { // make second store available data.stores[1].contextId = 2; emit updated(); } else if(step == 2) { // make items in the first store available data.stores[0].avail = true; emit storeUpdated(data.stores[0].contextId); } else if(step == 3) { // make the first store unavailable data.stores[0].contextId = -1; emit updated(); } else if(step == 4) { // make the first store available data.stores[0].contextId = 3; emit updated(); } else if(step == 5) { // make the second store unavailable data.stores[1].contextId = -1; emit updated(); } else if(step == 6) { // make the first store unavailable data.stores[0].contextId = -1; emit updated(); } else { // stop, we're done t.stop(); } ++step; } }; //---------------------------------------------------------------------------- // TestProvider //---------------------------------------------------------------------------- Provider::Context *TestProvider::createContext(const QString &type) { if(type == "keystorelist") return new TestKeyStoreListContext(this); else return 0; } //---------------------------------------------------------------------------- // TestPlugin //---------------------------------------------------------------------------- class TestPlugin : public QObject, public QCAPlugin { Q_OBJECT Q_INTERFACES(QCAPlugin) public: virtual Provider *createProvider() { return new TestProvider; } }; #include "qca-test.moc" Q_EXPORT_PLUGIN2(qca_test, TestPlugin);