qca/plugins/qca-softstore/qca-softstore.cpp
Justin Karneges ab782c5ff4 remove unnecessary secure array usage from cert api
svn path=/trunk/kdesupport/qca/; revision=674313
2007-06-12 02:30:58 +00:00

1532 lines
28 KiB
C++

/*
* Copyright (C) 2007 Alon Bar-Lev <alon.barlev@gmail.com>
*
* 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 WITHANY 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 <QtCrypto>
#include <QtPlugin>
#include <QHash>
#include <QFile>
using namespace QCA;
// qPrintable is ASCII only!!!
#define myPrintable(s) (s).toUtf8 ().constData ()
namespace softstoreQCAPlugin {
class softstoreKeyStoreListContext;
static softstoreKeyStoreListContext *s_keyStoreList = NULL;
enum KeyType {
keyTypeInvalid,
keyTypePKCS12,
keyTypePKCS8Inline,
keyTypePKCS8FilePEM,
keyTypePKCS8FileDER
};
enum PublicType {
publicTypeInvalid,
publicTypeX509Chain
};
struct SoftStoreEntry {
QString name;
CertificateChain chain;
KeyType keyReferenceType;
QString keyReference;
bool noPassphrase;
int unlockTimeout;
};
class softstoreRSAContext : public RSAContext
{
Q_OBJECT
private:
bool _has_privateKeyRole;
SoftStoreEntry _entry;
QString _serialized;
RSAPrivateKey _privkey;
RSAPrivateKey _privkeySign;
RSAPublicKey _pubkey;
QDateTime dueTime;
public:
softstoreRSAContext (
const SoftStoreEntry &entry,
const QString &serialized,
Provider *p
) : RSAContext (p) {
QCA_logTextMessage (
"softstoreRSAContext::softstoreRSAContext1 - entry",
Logger::Debug
);
_has_privateKeyRole = true;
_entry = entry;
_serialized = serialized;
_pubkey = _entry.chain.primary ().subjectPublicKey ().toRSA ();
QCA_logTextMessage (
"softstoreRSAContext::softstoreRSAContext1 - return",
Logger::Debug
);
}
softstoreRSAContext (const softstoreRSAContext &from) : RSAContext (from.provider ()) {
QCA_logTextMessage (
"softstoreRSAContext::softstoreRSAContextC - entry",
Logger::Debug
);
_has_privateKeyRole = from._has_privateKeyRole;
_entry = from._entry;
_serialized = from._serialized;
_pubkey = from._pubkey;
_privkey = from._privkey;
QCA_logTextMessage (
"softstoreRSAContext::softstoreRSAContextC - return",
Logger::Debug
);
}
~softstoreRSAContext () {
QCA_logTextMessage (
"softstoreRSAContext::~softstoreRSAContext - entry",
Logger::Debug
);
QCA_logTextMessage (
"softstoreRSAContext::~softstoreRSAContext - return",
Logger::Debug
);
}
virtual
Provider::Context *
clone () const {
return new softstoreRSAContext (*this);
}
public:
virtual
bool
isNull () const {
return _pubkey.isNull ();
}
virtual
PKey::Type
type () const {
return _pubkey.type ();
}
virtual
bool
isPrivate () const {
return _has_privateKeyRole;
}
virtual
bool
canExport () const {
return !_has_privateKeyRole;
}
virtual
void
convertToPublic () {
QCA_logTextMessage (
"softstoreRSAContext::convertToPublic - entry",
Logger::Debug
);
if (_has_privateKeyRole) {
_has_privateKeyRole = false;
}
QCA_logTextMessage (
"softstoreRSAContext::convertToPublic - return",
Logger::Debug
);
}
virtual
int
bits () const {
return _pubkey.bitSize ();
}
virtual
int
maximumEncryptSize (
EncryptionAlgorithm alg
) const {
return _pubkey.maximumEncryptSize (alg);
}
virtual
SecureArray
encrypt (
const SecureArray &in,
EncryptionAlgorithm alg
) {
return _pubkey.encrypt (in, alg);
}
virtual
bool
decrypt (
const SecureArray &in,
SecureArray *out,
EncryptionAlgorithm alg
) {
if (_ensureAccess ()) {
return _privkey.decrypt (in, out, alg);
}
else {
return false;
}
}
virtual
void
startSign (
SignatureAlgorithm alg,
SignatureFormat format
) {
if (_ensureAccess ()) {
/*
* We must use one object thought
* signing, so it won't expire by
* it-self or during passphrase.
*/
_privkeySign = _privkey;
_privkeySign.startSign (alg, format);
}
}
virtual
void
startVerify (
SignatureAlgorithm alg,
SignatureFormat sf
) {
_pubkey.startVerify (alg, sf);
}
virtual
void
update (
const SecureArray &in
) {
if (_has_privateKeyRole) {
_privkeySign.update (in);
}
else {
_pubkey.update (in);
}
}
virtual
SecureArray
endSign () {
SecureArray r = _privkeySign.signature ();
_privkeySign = RSAPrivateKey ();
return r;
}
virtual
bool
validSignature (
const SecureArray &sig
) {
return _pubkey.validSignature (sig);
}
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 _pubkey.n ();
}
virtual
BigInteger
e () const {
return _pubkey.e ();
}
virtual
BigInteger
p () const {
return BigInteger();
}
virtual
BigInteger
q () const {
return BigInteger();
}
virtual
BigInteger
d () const {
return BigInteger();
}
public:
PublicKey
_publicKey () const {
return _pubkey;
}
bool
_ensureAccess () {
bool ret = false;
QCA_logTextMessage (
"softstoreRSAContext::_ensureAccess - entry",
Logger::Debug
);
if (_entry.unlockTimeout != -1) {
if (dueTime >= QDateTime::currentDateTime ()) {
QCA_logTextMessage (
"softstoreRSAContext::_ensureAccess - dueTime reached, clearing",
Logger::Debug
);
_privkey = RSAPrivateKey ();
}
}
if (!_privkey.isNull ()) {
ret = true;
}
else {
KeyStoreEntry entry;
KeyStoreEntryContext *context = NULL;
QString storeId, storeName;
ConvertResult cresult;
QCA_logTextMessage (
"softstoreRSAContext::_ensureAccess - no current key, creating",
Logger::Debug
);
// too lazy to create scope
context = reinterpret_cast<KeyStoreListContext *> (s_keyStoreList)->entryPassive (_serialized);
if (context != NULL) {
storeId = context->storeId ();
storeName = context->storeName ();
entry.change (context);
}
while (!ret) {
SecureArray passphrase;
switch (_entry.keyReferenceType) {
case keyTypeInvalid:
case keyTypePKCS8Inline:
break;
case keyTypePKCS12:
case keyTypePKCS8FilePEM:
case keyTypePKCS8FileDER:
{
QFile file (_entry.keyReference);
while (!file.open (QIODevice::ReadOnly)) {
TokenAsker asker;
asker.ask (
KeyStoreInfo (KeyStore::SmartCard, storeId, storeName),
entry,
context
);
asker.waitForResponse ();
if (!asker.accepted ()) {
goto cleanup1;
}
}
}
break;
}
if (!_entry.noPassphrase) {
PasswordAsker asker;
asker.ask (
Event::StylePassphrase,
KeyStoreInfo (KeyStore::User, storeId, storeName),
entry,
context
);
asker.waitForResponse ();
passphrase = asker.password ();
if (!asker.accepted ()) {
goto cleanup1;
}
}
switch (_entry.keyReferenceType) {
case keyTypeInvalid:
break;
case keyTypePKCS12:
{
KeyBundle bundle = KeyBundle::fromFile (
_entry.keyReference,
passphrase,
&cresult
);
if (cresult == ConvertGood) {
_privkey = bundle.privateKey ().toRSA ();
ret = true;
}
}
break;
case keyTypePKCS8Inline:
{
PrivateKey k = PrivateKey::fromDER (
Base64 ().stringToArray (_entry.keyReference),
passphrase,
&cresult
);
if (cresult == ConvertGood) {
_privkey = k.toRSA ();
ret = true;
}
}
break;
case keyTypePKCS8FilePEM:
{
PrivateKey k = PrivateKey::fromPEMFile (
_entry.keyReference,
passphrase,
&cresult
);
if (cresult == ConvertGood) {
_privkey = k.toRSA ();
ret = true;
}
}
break;
case keyTypePKCS8FileDER:
{
QFile file (_entry.keyReference);
if (file.open (QIODevice::ReadOnly)) {
QByteArray contents = file.readAll ();
PrivateKey k = PrivateKey::fromDER (
contents,
passphrase,
&cresult
);
if (cresult == ConvertGood) {
_privkey = k.toRSA ();
ret = true;
}
}
}
break;
}
}
if (_entry.unlockTimeout != -1) {
dueTime = QDateTime::currentDateTime ().addSecs (_entry.unlockTimeout);
}
cleanup1:
;
}
QCA_logTextMessage (
QString ().sprintf (
"softstoreRSAContext::_ensureAccess - return ret=%d",
ret ? 1 : 0
),
Logger::Debug
);
return ret;
}
};
class softstorePKeyContext : public PKeyContext
{
private:
PKeyBase *_k;
public:
softstorePKeyContext (Provider *p) : PKeyContext (p) {
_k = NULL;
}
~softstorePKeyContext () {
delete _k;
_k = NULL;
}
virtual
Provider::Context *
clone () const {
softstorePKeyContext *c = new softstorePKeyContext (*this);
c->_k = (PKeyBase *)_k->clone();
return c;
}
public:
virtual
QList<PKey::Type>
supportedTypes () const {
QList<PKey::Type> list;
list += PKey::RSA;
return list;
}
virtual
QList<PKey::Type>
supportedIOTypes () const {
QList<PKey::Type> list;
list += PKey::RSA;
return list;
}
virtual
QList<PBEAlgorithm>
supportedPBEAlgorithms () const {
QList<PBEAlgorithm> list;
return list;
}
virtual
PKeyBase *
key () {
return _k;
}
virtual
const PKeyBase *
key () const {
return _k;
}
virtual
void
setKey (PKeyBase *key) {
delete _k;
_k = key;
}
virtual
bool
importKey (
const PKeyBase *key
) {
Q_UNUSED(key);
return false;
}
static
int
passphrase_cb (
char *buf,
int size,
int rwflag,
void *u
) {
Q_UNUSED(buf);
Q_UNUSED(size);
Q_UNUSED(rwflag);
Q_UNUSED(u);
return 0;
}
virtual
SecureArray
publicToDER () const {
return static_cast<softstoreRSAContext *>(_k)->_publicKey ().toDER ();
}
virtual
QString
publicToPEM () const {
return static_cast<softstoreRSAContext *>(_k)->_publicKey ().toPEM ();
}
virtual
ConvertResult
publicFromDER (
const SecureArray &in
) {
Q_UNUSED(in);
return ErrorDecode;
}
virtual
ConvertResult
publicFromPEM (
const QString &s
) {
Q_UNUSED(s);
return ErrorDecode;
}
virtual
SecureArray
privateToDER(
const SecureArray &passphrase,
PBEAlgorithm pbe
) const {
Q_UNUSED(passphrase);
Q_UNUSED(pbe);
return SecureArray ();
}
virtual
QString
privateToPEM (
const SecureArray &passphrase,
PBEAlgorithm pbe
) const {
Q_UNUSED(passphrase);
Q_UNUSED(pbe);
return QString ();
}
virtual
ConvertResult
privateFromDER (
const SecureArray &in,
const SecureArray &passphrase
) {
Q_UNUSED(in);
Q_UNUSED(passphrase);
return ErrorDecode;
}
virtual
ConvertResult
privateFromPEM (
const QString &s,
const SecureArray &passphrase
) {
Q_UNUSED(s);
Q_UNUSED(passphrase);
return ErrorDecode;
}
};
class softstoreKeyStoreEntryContext : public KeyStoreEntryContext
{
private:
KeyStoreEntry::Type _item_type;
KeyBundle _key;
SoftStoreEntry _entry;
QString _serialized;
public:
softstoreKeyStoreEntryContext (
const KeyBundle &key,
const SoftStoreEntry &entry,
const QString &serialized,
Provider *p
) : KeyStoreEntryContext(p) {
_item_type = KeyStoreEntry::TypeKeyBundle;
_key = key;
_entry = entry;
_serialized = serialized;
}
softstoreKeyStoreEntryContext (
const softstoreKeyStoreEntryContext &from
) : KeyStoreEntryContext(from) {
_item_type = from._item_type;
_key = from._key;
_entry = from._entry;
_serialized = from._serialized;
}
virtual
Provider::Context *
clone () const {
return new softstoreKeyStoreEntryContext (*this);
}
public:
virtual
KeyStoreEntry::Type
type () const {
return KeyStoreEntry::TypeKeyBundle;
}
virtual
QString
name () const {
return _entry.name;
}
virtual
QString
id () const {
return _entry.name;
}
virtual
KeyBundle
keyBundle () const {
return _key;
}
virtual
Certificate
certificate () const {
return _entry.chain.primary ();
}
virtual
QString
storeId () const {
return QString ().sprintf ("%s/%s", "qca-softstore", myPrintable (_entry.name));
}
virtual
QString
storeName () const {
return _entry.name;
}
virtual
bool
ensureAccess () {
return static_cast<softstoreRSAContext *>(static_cast<PKeyContext *>(_key.privateKey ().context ())->key ())->_ensureAccess ();
}
virtual
QString
serialize () const {
return _serialized;
}
};
class softstoreKeyStoreListContext : public KeyStoreListContext
{
Q_OBJECT
private:
int _last_id;
QList<SoftStoreEntry> _entries;
public:
softstoreKeyStoreListContext (Provider *p) : KeyStoreListContext (p) {
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::softstoreKeyStoreListContext - entry Provider=%p",
(void *)p
),
Logger::Debug
);
_last_id = 0;
QCA_logTextMessage (
"softstoreKeyStoreListContext::softstoreKeyStoreListContext - return",
Logger::Debug
);
}
~softstoreKeyStoreListContext () {
QCA_logTextMessage (
"softstoreKeyStoreListContext::~softstoreKeyStoreListContext - entry",
Logger::Debug
);
s_keyStoreList = NULL;
QCA_logTextMessage (
"softstoreKeyStoreListContext::~softstoreKeyStoreListContext - return",
Logger::Debug
);
}
virtual
Provider::Context *
clone () const {
QCA_logTextMessage (
"softstoreKeyStoreListContext::clone - entry/return",
Logger::Debug
);
return NULL;
}
public:
virtual
void
start () {
QCA_logTextMessage (
"softstoreKeyStoreListContext::start - entry",
Logger::Debug
);
QMetaObject::invokeMethod(this, "doReady", Qt::QueuedConnection);
QCA_logTextMessage (
"softstoreKeyStoreListContext::start - return",
Logger::Debug
);
}
virtual
void
setUpdatesEnabled (bool enabled) {
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::setUpdatesEnabled - entry/return enabled=%d",
enabled ? 1 : 0
),
Logger::Debug
);
}
virtual
KeyStoreEntryContext *
entry (
int id,
const QString &entryId
) {
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::entry - entry/return id=%d entryId='%s'",
id,
myPrintable (entryId)
),
Logger::Debug
);
Q_UNUSED(id);
Q_UNUSED(entryId);
return NULL;
}
virtual
KeyStoreEntryContext *
entryPassive (
const QString &serialized
) {
KeyStoreEntryContext *entry = NULL;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::entryPassive - entry serialized='%s'",
myPrintable (serialized)
),
Logger::Debug
);
if (serialized.startsWith ("qca-softstore/")) {
SoftStoreEntry sentry;
if (_deserializeSoftStoreEntry (serialized, sentry)) {
entry = _keyStoreEntryBySoftStoreEntry (sentry);
}
}
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::entryPassive - return entry=%p",
(void *)entry
),
Logger::Debug
);
return entry;
}
virtual
KeyStore::Type
type (int id) const {
Q_UNUSED(id);
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::type - entry/return id=%d",
id
),
Logger::Debug
);
return KeyStore::User;
}
virtual
QString
storeId (int id) const {
QString ret;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::storeId - entry id=%d",
id
),
Logger::Debug
);
ret = "qca-softstore";
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::storeId - return ret=%s",
myPrintable (ret)
),
Logger::Debug
);
return ret;
}
virtual
QString
name (int id) const {
QString ret;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::name - entry id=%d",
id
),
Logger::Debug
);
ret = "User Software Store";
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::name - return ret=%s",
myPrintable (ret)
),
Logger::Debug
);
return ret;
}
virtual
QList<KeyStoreEntry::Type>
entryTypes (int id) const {
Q_UNUSED(id);
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::entryTypes - entry/return id=%d",
id
),
Logger::Debug
);
QList<KeyStoreEntry::Type> list;
list += KeyStoreEntry::TypeKeyBundle;
list += KeyStoreEntry::TypeCertificate;
return list;
}
virtual
QList<int>
keyStores () {
QList<int> list;
QCA_logTextMessage (
"softstoreKeyStoreListContext::keyStores - entry",
Logger::Debug
);
list += _last_id;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::keyStores - return out.size()=%d",
list.size ()
),
Logger::Debug
);
return list;
}
virtual
QList<KeyStoreEntryContext *>
entryList (int id) {
QList<KeyStoreEntryContext*> list;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::entryList - entry id=%d",
id
),
Logger::Debug
);
foreach (SoftStoreEntry e, _entries) {
list += _keyStoreEntryBySoftStoreEntry (e);
}
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::entryList - return out.size()=%d",
list.size ()
),
Logger::Debug
);
return list;
}
void
_emit_diagnosticText (
const QString &t
) {
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_emit_diagnosticText - entry t='%s'",
myPrintable (t)
),
Logger::Debug
);
QCA_logTextMessage (t, Logger::Warning);
emit diagnosticText (t);
QCA_logTextMessage (
"softstoreKeyStoreListContext::_emit_diagnosticText - return",
Logger::Debug
);
}
private slots:
void
doReady () {
QCA_logTextMessage (
"softstoreKeyStoreListContext::doReady - entry",
Logger::Debug
);
emit busyEnd ();
QCA_logTextMessage (
"softstoreKeyStoreListContext::doReady - return",
Logger::Debug
);
}
void
doUpdated () {
QCA_logTextMessage (
"softstoreKeyStoreListContext::doUpdated - entry",
Logger::Debug
);
emit updated ();
QCA_logTextMessage (
"softstoreKeyStoreListContext::doUpdated - return",
Logger::Debug
);
}
public:
void
_updateConfig (const QVariantMap &config, const int maxEntries) {
QCA_logTextMessage (
"softstoreKeyStoreListContext::_updateConfig - entry",
Logger::Debug
);
QMap<QString, KeyType> keyTypeMap;
keyTypeMap["pkcs12"] = keyTypePKCS12;
keyTypeMap["pkcs8"] = keyTypePKCS8Inline;
keyTypeMap["pkcs8-file-pem"] = keyTypePKCS8FilePEM;
keyTypeMap["pkcs8-file-der"] = keyTypePKCS8FileDER;
QMap<QString, PublicType> publicTypeMap;
publicTypeMap["x509chain"] = publicTypeX509Chain;
_last_id++;
_entries.clear ();
for (int i=0;i<maxEntries;i++) {
if (config[QString ().sprintf ("entry_%02d_enabled", i)].toBool ()) {
ConvertResult cresult;
SoftStoreEntry entry;
PublicType publicType = publicTypeInvalid;
entry.name = config[QString ().sprintf ("entry_%02d_name", i)].toString ();
QString stringReferenceType = config[QString ().sprintf ("entry_%02d_private_type", i)].toString ();
QString stringPublicType = config[QString ().sprintf ("entry_%02d_public_type", i)].toString ();
entry.noPassphrase = config[QString ().sprintf ("entry_%02d_no_passphrase", i)].toBool ();
entry.unlockTimeout = config[QString ().sprintf ("entry_%02d_unlock_timeout", i)].toInt ();
if (publicTypeMap.contains (stringPublicType)) {
publicType = publicTypeMap[stringPublicType];
}
else {
_emit_diagnosticText (
QString ().sprintf (
"Software Store: Bad public key type of '%s' entry.\n",
myPrintable (entry.name)
)
);
goto cleanup1;
}
if (keyTypeMap.contains (stringReferenceType)) {
entry.keyReferenceType = keyTypeMap[stringReferenceType];
}
else {
_emit_diagnosticText (
QString ().sprintf (
"Software Store: Bad private key type of '%s' entry.\n",
myPrintable (entry.name)
)
);
goto cleanup1;
}
entry.keyReference = config[QString ().sprintf ("entry_%02d_private", i)].toString ();
switch (publicType) {
case publicTypeInvalid:
goto cleanup1;
break;
case publicTypeX509Chain:
QStringList base64certs = config[QString ().sprintf ("entry_%02d_public", i)].toString ().split ("!");
foreach (QString s, base64certs) {
entry.chain += Certificate::fromDER (
Base64 ().stringToArray (s).toByteArray (),
&cresult
);
}
if (cresult != ConvertGood) {
_emit_diagnosticText (
QString ().sprintf (
"Software Store: Cannot load certificate of '%s' entry.\n",
myPrintable (entry.name)
)
);
goto cleanup1;
}
break;
}
_entries += entry;
cleanup1:
; //nothing to do for this entry.
}
}
QMetaObject::invokeMethod(s_keyStoreList, "doUpdated", Qt::QueuedConnection);
QCA_logTextMessage (
"softstoreKeyStoreListContext::_updateConfig - return",
Logger::Debug
);
}
private:
QString
_serializeSoftStoreEntry (
const SoftStoreEntry &entry
) const {
QString serialized;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_serializeSoftStoreEntry - entry name=%s",
myPrintable (entry.name)
),
Logger::Debug
);
serialized = QString ().sprintf (
"qca-softstore/0/%s/%d/%s/%d/%d/x509chain/",
myPrintable (_escapeString (entry.name)),
entry.keyReferenceType,
myPrintable (_escapeString (entry.keyReference)),
entry.noPassphrase ? 1 : 0,
entry.unlockTimeout
);
QStringList list;
foreach (Certificate i, entry.chain) {
list += _escapeString (Base64 ().arrayToString (i.toDER ()));
}
serialized.append (list.join ("/"));
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_serializeSoftStoreEntry - return serialized='%s'",
myPrintable (serialized)
),
Logger::Debug
);
return serialized;
}
bool
_deserializeSoftStoreEntry (
const QString &serialized,
SoftStoreEntry &entry
) const {
bool ret = false;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_deserializeSoftStoreEntry - entry from='%s'",
myPrintable (serialized)
),
Logger::Debug
);
entry = SoftStoreEntry ();
QStringList list = serialized.split ("/");
int n=0;
if (list.size () < 8) {
goto cleanup;
}
if (list[n++] != "qca-softstore") {
goto cleanup;
}
if (list[n++].toInt () != 0) {
goto cleanup;
}
entry.name = _unescapeString (list[n++]);
entry.keyReferenceType = (KeyType)list[n++].toInt ();
entry.keyReference = _unescapeString (list[n++]);
entry.noPassphrase = list[n++].toInt () != 0;
entry.unlockTimeout = list[n++].toInt ();
n++; // skip public key for now.
while (n < list.size ()) {
Certificate cert = Certificate::fromDER (
Base64 ().stringToArray (_unescapeString (list[n++])).toByteArray ()
);
if (cert.isNull ()) {
goto cleanup;
}
entry.chain += cert;
}
ret = true;
cleanup:
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_deserializeSoftStoreEntry - return ret=%d chain.size()=%d",
ret ? 1 : 0,
entry.chain.size ()
),
Logger::Debug
);
return ret;
}
softstoreKeyStoreEntryContext *
_keyStoreEntryBySoftStoreEntry (
const SoftStoreEntry &sentry
) const {
softstoreKeyStoreEntryContext *entry = NULL;
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_keyStoreEntryBySoftStoreEntry - entry name=%s",
myPrintable (sentry.name)
),
Logger::Debug
);
QString serialized = _serializeSoftStoreEntry (sentry);
softstoreRSAContext *rsakey = new softstoreRSAContext (
sentry,
serialized,
provider()
);
softstorePKeyContext *pkc = new softstorePKeyContext (provider ());
pkc->setKey (rsakey);
PrivateKey privkey;
privkey.change (pkc);
KeyBundle key;
key.setCertificateChainAndKey (
sentry.chain,
privkey
);
entry = new softstoreKeyStoreEntryContext (
key,
sentry,
serialized,
provider ()
);
QCA_logTextMessage (
QString ().sprintf (
"softstoreKeyStoreListContext::_keyStoreEntryBySoftStoreEntry - return entry=%p",
(void *)entry
),
Logger::Debug
);
return entry;
}
QString
_escapeString (
const QString &from
) const {
QString to;
foreach (QChar c, from) {
if (c == '/' || c == '\\') {
to += QString ().sprintf ("\\x%04x", c.unicode ());
}
else {
to += c;
}
}
return to;
}
QString
_unescapeString (
const QString &from
) const {
QString to;
for (int i=0;i<from.size ();i++) {
QChar c = from[i];
if (c == '\\') {
to += QChar ((ushort)from.mid (i+2, 4).toInt (0, 16));
i+=5;
}
else {
to += c;
}
}
return to;
}
};
}
using namespace softstoreQCAPlugin;
class softstoreProvider : public Provider
{
private:
static const int _CONFIG_MAX_ENTRIES;
QVariantMap _config;
public:
softstoreProvider () {
}
~softstoreProvider () {
}
public:
virtual
int
qcaVersion() const {
return QCA_VERSION;
}
virtual
void
init () {
}
virtual
QString
name () const {
return "qca-softstore";
}
virtual
QStringList
features () const {
QCA_logTextMessage (
"softstoreProvider::features - entry/return",
Logger::Debug
);
QStringList list;
list += "pkey";
list += "keystorelist";
return list;
}
virtual
Context *
createContext (
const QString &type
) {
Provider::Context *context = NULL;
QCA_logTextMessage (
QString ().sprintf (
"softstoreProvider::createContext - entry type='%s'",
myPrintable (type)
),
Logger::Debug
);
if (type == "keystorelist") {
if (s_keyStoreList == NULL) {
s_keyStoreList = new softstoreKeyStoreListContext (this);
s_keyStoreList->_updateConfig (_config, _CONFIG_MAX_ENTRIES);
}
context = s_keyStoreList;
}
QCA_logTextMessage (
QString ().sprintf (
"softstoreProvider::createContext - return context=%p",
(void *)context
),
Logger::Debug
);
return context;
}
virtual
QVariantMap
defaultConfig () const {
QVariantMap mytemplate;
QCA_logTextMessage (
"softstoreProvider::defaultConfig - entry/return",
Logger::Debug
);
mytemplate["formtype"] = "http://affinix.com/qca/forms/qca-softstore#1.0";
for (int i=0;i<_CONFIG_MAX_ENTRIES;i++) {
mytemplate[QString ().sprintf ("entry_%02d_enabled", i)] = false;
mytemplate[QString ().sprintf ("entry_%02d_name", i)] = "";
mytemplate[QString ().sprintf ("entry_%02d_public_type", i)] = "";
mytemplate[QString ().sprintf ("entry_%02d_private_type", i)] = "";
mytemplate[QString ().sprintf ("entry_%02d_public", i)] = "";
mytemplate[QString ().sprintf ("entry_%02d_private", i)] = "";
mytemplate[QString ().sprintf ("entry_%02d_unlock_timeout", i)] = -1;
mytemplate[QString ().sprintf ("entry_%02d_no_passphrase", i)] = false;
}
return mytemplate;
}
virtual
void
configChanged (const QVariantMap &config) {
QCA_logTextMessage (
"softstoreProvider::configChanged - entry",
Logger::Debug
);
_config = config;
if (s_keyStoreList != NULL) {
s_keyStoreList->_updateConfig (_config, _CONFIG_MAX_ENTRIES);
}
QCA_logTextMessage (
"softstoreProvider::configChanged - return",
Logger::Debug
);
}
};
const int softstoreProvider::_CONFIG_MAX_ENTRIES = 50;
class softstorePlugin : public QObject, public QCAPlugin
{
Q_OBJECT
Q_INTERFACES(QCAPlugin)
public:
virtual Provider *createProvider() { return new softstoreProvider; }
};
#include "qca-softstore.moc"
Q_EXPORT_PLUGIN2(qca_softstore, softstorePlugin)