qca/include/QtCrypto/qca_keystore.h
Justin Karneges 35e5d4d4ba Q_DISABLE_COPY
svn path=/trunk/kdesupport/qca/; revision=669727
2007-05-30 07:02:34 +00:00

643 lines
15 KiB
C++

/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
/**
\file qca_keystore.h
Header file for classes that provide and manage keys
\note You should not use this header directly from an
application. You should just use <tt> \#include \<QtCrypto>
</tt> instead.
*/
#ifndef QCA_KEYSTORE_H
#define QCA_KEYSTORE_H
#include "qca_core.h"
#include "qca_cert.h"
namespace QCA
{
class KeyStoreTracker;
class KeyStoreManagerPrivate;
class KeyStorePrivate;
/**
\class KeyStoreEntry qca_keystore.h QtCrypto
Single entry in a KeyStore
This is a container for any kind of object in a KeyStore
(such as PGP keys, or X.509 certificates / private keys).
KeyStoreEntry entities are normally accessed through the KeyStore,
however it is possible to access KeyStoreEntry objects directly,
using a persistent id().
\code
QString entry_id = someKeyStoreEntry.id();
[ app saves entry_id to disk ]
[ app quits ]
...
[ app launches ]
[ app reads entry_id from disk ]
KeyStoreEntry entry(entry_id);
printf("Entry name: [%s]\n", qPrintable(entry.name()));
\endcode
Keep in mind that retrieving a passive entry's content
(e.g. with entry.certificate()) may return a null object.
To ensure the entry is available, do:
\code
if(entry.ensureAvailable())
{
Certificate cert = entry.certificate();
...
}
\endcode
ensureAvailable() blocks and may cause hardware access, but
if it completes successfully then you may use the entry's
content. It also means, in the case of a Smart Card token,
that it is probably inserted.
To watch this id asynchronously, you would do:
\code
KeyStoreEntryWatcher *watcher = new KeyStoreEntryWatcher(entry);
connect(watcher, SIGNAL(available()), SLOT(entry_available()));
...
void entry_available()
{
// entry now available
Certificate cert = watcher->entry().certificate();
}
\endcode
Note that a provider can supply valid content objects even
for unavailable entries, if they have enough metadata to
provide that (qca-pkcs11 for example, puts the entire cert
in the id).
Now, even though an entry may be available, it does not
mean you have access to use it for operations. For
example, a KeyBundle offered by a Smart Card that is
available is guaranteed to give you valid objects, however
as soon as you try to use the PrivateKey object for a
signing operation, a PIN might be asked for. You can call
ensureAccess() if you want to synchronously provide the PIN
early on:
\code
if(entry.ensureAccess())
{
// do private key stuff
...
}
\endcode
Note that you don't have to call ensureAvailable() before
ensureAccess(). Calling the latter is enough to imply
both.
After an application is configured to use a particular key,
it is expected that its usual running procedure will be:
- Construct KeyStoreEntry from the known id.
- If the content object is not available, wait for it
(with either ensureAvailable() or KeyStoreEntryWatcher).
- Pass the content object(s) to a high level operation like TLS.
In this case, any PIN prompting and private key operations
would be caused/handled from the TLS object.
*/
class QCA_EXPORT KeyStoreEntry : public Algorithm
{
public:
/**
The type of entry in the KeyStore
*/
enum Type
{
TypeKeyBundle,
TypeCertificate,
TypeCRL,
TypePGPSecretKey,
TypePGPPublicKey
};
/**
Create an empty KeyStoreEntry
*/
KeyStoreEntry();
/**
Create a passive KeyStoreEntry based on a serialized
string
\sa fromString
*/
KeyStoreEntry(const QString &serialized);
/**
Standard copy constructor
\param from the source entry
*/
KeyStoreEntry(const KeyStoreEntry &from);
~KeyStoreEntry();
/**
Standard assignment operator
\param from the source entry
*/
KeyStoreEntry & operator=(const KeyStoreEntry &from);
/**
Test if this key is empty (null)
*/
bool isNull() const;
/**
Test if the key is available for use.
A key is considered available if the KeyStore
that it is part of is present.
\sa ensureAvailable
\sa isAccessible
*/
bool isAvailable() const;
/**
Test if the key is currently accessible.
This means that the private key part can be used
at this time. For a smartcard, this means that all
required operations (e.g. login / PIN entry) are
completed.
If isAccessible() is true, then the key
is necessarily available (i.e. isAvailable() is
also true).
\sa ensureAccessible
\sa isAvailable
*/
bool isAccessible() const;
/**
Determine the type of key stored in this object
*/
Type type() const;
/**
The name associated with the key stored in this object
*/
QString name() const;
/**
The ID associated with the key stored in this object.
*/
QString id() const;
/**
The name of the KeyStore for this key object
*/
QString storeName() const;
/**
The id of the KeyStore for this key object
\sa KeyStore::id()
*/
QString storeId() const;
/**
Serialize into a string for use as a passive entry
*/
QString toString() const;
/**
Load a passive entry by using a serialized string
as input
\return the newly created KeyStoreEntry
*/
static KeyStoreEntry fromString(const QString &serialized);
/**
If a KeyBundle is stored in this object, return that
bundle.
*/
KeyBundle keyBundle() const;
/**
If a Certificate is stored in this object, return that
certificate.
*/
Certificate certificate() const;
/**
If a CRL is stored in this object, return the value
of the CRL
*/
CRL crl() const;
/**
If the key stored in this object is a private
PGP key, return the contents of that key.
*/
PGPKey pgpSecretKey() const;
/**
If the key stored in this object is either an
public or private PGP key, extract the public key
part of that PGP key.
*/
PGPKey pgpPublicKey() const;
/**
Returns true if the entry is available, otherwise false.
Available means that the retrieval functions (like
keyBundle(), certificate(), pgpPublicKey(), etc) will
return non-null objects. Entries retrieved from a
KeyStore are always available, and therefore it is not
necessary to call this function. Calling this function
on an already available entry may cause the entry to
be refreshed.
\sa isAvailable
\sa ensureAccess
\note This function is blocking.
*/
bool ensureAvailable();
/**
Like ensureAvailable, but will also ensure
that the token is inserted / PIN is provided
if needed.
\sa isAccessible
\sa ensureAvailable
*/
bool ensureAccess();
private:
class Private;
Private *d;
friend class KeyStoreTracker;
};
class QCA_EXPORT KeyStoreEntryWatcher : public QObject
{
Q_OBJECT
public:
explicit KeyStoreEntryWatcher(const KeyStoreEntry &e, QObject *parent = 0);
~KeyStoreEntryWatcher();
KeyStoreEntry entry() const;
Q_SIGNALS:
void available();
void unavailable();
private:
Q_DISABLE_COPY(KeyStoreEntryWatcher)
class Private;
friend class Private;
Private *d;
};
/**
\class KeyStore qca_keystore.h QtCrypto
General purpose key storage object
Examples of use of this are:
- systemstore: System TrustedCertificates
- accepted self-signed: Application TrustedCertificates
- apple keychain: User Identities
- smartcard: SmartCard Identities
- gnupg: PGPKeyring Identities,PGPPublicKeys
\note
- there can be multiple KeyStore objects referring to the same id
- when a KeyStore is constructed, it refers to a given id (deviceId)
and internal contextId. if the context goes away, the KeyStore
becomes invalid (isValid() == false), and unavailable() is emitted.
even if the device later reappears, the KeyStore remains invalid.
a new KeyStore will have to be created to use the device again.
*/
class QCA_EXPORT KeyStore : public QObject, public Algorithm
{
Q_OBJECT
public:
/**
The type of keystore
*/
enum Type
{
System, ///< objects such as root certificates
User, ///< objects such as Apple Keychain, KDE Wallet
Application, ///< for caching accepted self-signed certificates
SmartCard, ///< for smartcards
PGPKeyring ///< for a PGP keyring
};
/**
Obtain a specific KeyStore
\param id the identification for the key store
\param keyStoreManager the parent manager for this keystore
*/
KeyStore(const QString &id, KeyStoreManager *keyStoreManager);
~KeyStore();
/**
Check if this KeyStore is valid
\return true if the KeyStore is valid
*/
bool isValid() const;
/**
The KeyStore Type
*/
Type type() const;
/**
The name associated with the KeyStore
*/
QString name() const;
/**
The ID associated with the KeyStore
*/
QString id() const;
/**
Test if the KeyStore is writeable or not
\return true if the KeyStore is read-only
*/
bool isReadOnly() const;
/**
Turns on asynchronous mode for this KeyStore instance.
Normally, entryList() and writeEntry() are blocking
calls. However, if startAsynchronousMode() is called,
then these functions will return immediately. entryList()
will return with the latest known entries, or an empty
list if none are known yet (in this mode, updated() will
be emitted once the initial entries are known, even if the
store has not actually been altered). writeEntry() will
always return an empty string, and the entryWritten()
signal indicates the result of a write.
*/
void startAsynchronousMode();
/**
A list of the KeyStoreEntry objects in this store
*/
QList<KeyStoreEntry> entryList() const;
/**
test if the KeyStore holds trusted certificates (and CRLs)
*/
bool holdsTrustedCertificates() const;
/**
test if the KeyStore holds identities (eg KeyBundle or PGPSecretKey)
*/
bool holdsIdentities() const;
/**
test if the KeyStore holds PGPPublicKey objects
*/
bool holdsPGPPublicKeys() const;
/**
Add a entry to the KeyStore
Returns the entryId of the written entry or an empty
string on failure.
\param kb the KeyBundle to add to the KeyStore
*/
QString writeEntry(const KeyBundle &kb);
/**
\overload
\param cert the Certificate to add to the KeyStore
*/
QString writeEntry(const Certificate &cert);
/**
\overload
\param crl the CRL to add to the KeyStore
*/
QString writeEntry(const CRL &crl);
/**
\overload
\param key the PGPKey to add to the KeyStore
\return a ref to the key in the keyring
*/
QString writeEntry(const PGPKey &key);
/**
Delete the a specified KeyStoreEntry from this KeyStore
\param id the ID for the entry to be deleted
*/
bool removeEntry(const QString &id);
Q_SIGNALS:
/**
Emitted when the KeyStore is changed
*/
void updated();
/**
Emitted when the KeyStore becomes unavailable
*/
void unavailable();
/**
Emitted when an entry has been written, in asynchronous
mode. entryId is the newly written entry id on success,
or an empty string if the write failed.
*/
void entryWritten(const QString &entryId);
/**
Emitted when an entry has been removed, in asynchronous
mode. success indicates if the removal succeeded or not.
*/
void entryRemoved(bool success);
private:
Q_DISABLE_COPY(KeyStore)
friend class KeyStorePrivate;
KeyStorePrivate *d;
friend class KeyStoreManagerPrivate;
};
// holds key store information outside of a keystore object
class QCA_EXPORT KeyStoreInfo
{
public:
KeyStoreInfo();
KeyStoreInfo(KeyStore::Type type, const QString &id, const QString &name);
KeyStoreInfo(const KeyStoreInfo &from);
~KeyStoreInfo();
KeyStoreInfo & operator=(const KeyStoreInfo &from);
bool isNull() const;
KeyStore::Type type() const;
QString id() const;
QString name() const;
private:
class Private;
QSharedDataPointer<Private> d;
};
/**
\class KeyStoreManager qca_keystore.h QtCrypto
Access keystores, and monitor keystores for changes.
Before you can access a KeyStore, you must create a
KeyStoreManager. You then need to start()
the KeyStoreManager, and either wait for the busyFinished()
signal, or block using waitForBusyFinished().
If you know the KeyStoreEntry that you need, you can
use KeyStore passively, as described in the KeyStoreEntry
documentation.
*/
class QCA_EXPORT KeyStoreManager : public QObject
{
Q_OBJECT
public:
/**
Create a new KeyStoreManager
\param parent the parent for this object
*/
KeyStoreManager(QObject *parent = 0);
~KeyStoreManager();
/**
Initialize all key store providers
*/
static void start();
/**
Initialize a specific key store provider
*/
static void start(const QString &provider);
/**
Indicates if the manager is busy looking for key stores
*/
bool isBusy() const;
/**
Blocks until the manager is done looking for key stores
*/
void waitForBusyFinished();
/**
A list of all the key stores
*/
QStringList keyStores() const;
/**
The diagnostic result of key store operations, such as
warnings and errors
*/
static QString diagnosticText();
/**
Clears the diagnostic result log
*/
static void clearDiagnosticText();
/**
If you are not using the eventloop, call this to update
the object state to the present
*/
void sync();
Q_SIGNALS:
/**
emitted when the manager has started looking for key stores
*/
void busyStarted();
/**
emitted when the manager has finished looking for key stores
*/
void busyFinished();
/**
emitted when a new key store becomes available
*/
void keyStoreAvailable(const QString &id);
private:
Q_DISABLE_COPY(KeyStoreManager)
friend class KeyStoreManagerPrivate;
KeyStoreManagerPrivate *d;
friend class Global;
friend class KeyStorePrivate;
static void scan();
static void shutdown();
};
}
#endif