|
|
|
/*! @file
|
|
|
|
|
|
|
|
@id $Id$
|
|
|
|
*/
|
|
|
|
// 1 2 3 4 5 6 7 8
|
|
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
|
|
|
|
#ifndef __Tokentool_HXX__
|
|
|
|
#define __Tokentool_HXX__
|
|
|
|
|
|
|
|
#include <QMainWindow>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QProgressBar>
|
|
|
|
#include <QDateTime>
|
|
|
|
#include <QSslCertificate>
|
|
|
|
#include <ui_tokentool.hxx>
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
#include <cryptoki.hxx>
|
|
|
|
|
|
|
|
#if QT_VERSION >= 0x050000
|
|
|
|
namespace QSsl {
|
|
|
|
typedef AlternativeNameEntryType AlternateNameEntryType;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
inline QString qs(const std::string& s) {
|
|
|
|
return QString::fromStdString(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<std::string::size_type SIZE>
|
|
|
|
QString qs(const cryptoki::FixString<SIZE>& s) {
|
|
|
|
return QString::fromStdString(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
class Progress: public QProgressBar {
|
|
|
|
public:
|
|
|
|
Progress() {
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
Progress& steps(int incr) {
|
|
|
|
setMaximum(maximum()+incr);
|
|
|
|
setVisible(value()<maximum());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Progress& operator++() {
|
|
|
|
setValue(value()+1);
|
|
|
|
setVisible(value()<maximum());
|
|
|
|
if (value()>=maximum()) {
|
|
|
|
setMaximum(0);
|
|
|
|
setValue(0);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Progress& reset() {
|
|
|
|
setMinimum(0);
|
|
|
|
setMaximum(0);
|
|
|
|
setValue(0);
|
|
|
|
setVisible(false);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class tokentool: public QMainWindow, protected Ui::tokentool {
|
|
|
|
Q_OBJECT;
|
|
|
|
public:
|
|
|
|
tokentool(std::string lib="libcvP11.so", QWidget* p=0):
|
|
|
|
QMainWindow(p), _slot(0), _progress(new Progress) {
|
|
|
|
try {
|
|
|
|
setupUi(this);
|
|
|
|
statusBar()->addPermanentWidget(_progress, 2);
|
|
|
|
show();
|
|
|
|
_progress->steps(3);
|
|
|
|
_cryptoki = std::auto_ptr<cryptoki::Library>(new cryptoki::Library(lib));
|
|
|
|
++*_progress;
|
|
|
|
_certificates->addAction(actionDeleteSelectedCertificate);
|
|
|
|
libraryInfo(lib);
|
|
|
|
++*_progress;
|
|
|
|
on_actionRescan_triggered();
|
|
|
|
++*_progress;
|
|
|
|
} catch (...) {
|
|
|
|
QMessageBox::critical(this, tr("Initialization Failed"),
|
|
|
|
tr("SmardCard Initialization Failed"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private Q_SLOTS:
|
|
|
|
void on_actionRescan_triggered() {
|
|
|
|
qDebug()<<__PRETTY_FUNCTION__;
|
|
|
|
static bool lock(false);
|
|
|
|
if (lock) return;
|
|
|
|
lock = true;
|
|
|
|
try {
|
|
|
|
_slot = 0;
|
|
|
|
_slots->clear();
|
|
|
|
_slotList = _cryptoki->slotList(false);
|
|
|
|
_progress->steps(_slotList.size());
|
|
|
|
for (cryptoki::SlotList::iterator it(_slotList.begin());
|
|
|
|
it!=_slotList.end(); ++it) {
|
|
|
|
qDebug()<<"Add Slot";
|
|
|
|
QAction* a(_slots->addAction(qs(it->slotinfo().slotDescription)));
|
|
|
|
a->setCheckable(true);
|
|
|
|
a->setData((qulonglong)&*it);
|
|
|
|
assert(connect(a, SIGNAL(triggered(bool)), SLOT(chosen(bool))));
|
|
|
|
if (!_slot) a->trigger();
|
|
|
|
++*_progress;
|
|
|
|
}
|
|
|
|
qDebug()<<"DONE";
|
|
|
|
} catch (...) {} // ignore
|
|
|
|
lock = false;
|
|
|
|
on__certificates_itemSelectionChanged();
|
|
|
|
}
|
|
|
|
void on_actionDeleteSelectedCertificate_triggered() {
|
|
|
|
QList<QTreeWidgetItem*> items(_certificates->selectedItems());
|
|
|
|
if (items.size()>0) deleteCert(items[0]);
|
|
|
|
}
|
|
|
|
void on__certificates_itemSelectionChanged() {
|
|
|
|
actionDeleteSelectedCertificate
|
|
|
|
->setEnabled(_certificates->selectedItems().size()
|
|
|
|
&&!_pin->text().isEmpty());
|
|
|
|
}
|
|
|
|
void on__pin_textChanged(const QString&) {
|
|
|
|
on__certificates_itemSelectionChanged();
|
|
|
|
}
|
|
|
|
void chosen(bool) {
|
|
|
|
_pin->clear();
|
|
|
|
QAction* a(qobject_cast<QAction*>(sender()));
|
|
|
|
a->setChecked(true);
|
|
|
|
QMenu* m(qobject_cast<QMenu*>(a->parent()));
|
|
|
|
QObjectList actions(m->children());
|
|
|
|
for (QObjectList::iterator it(actions.begin());it!=actions.end(); ++it)
|
|
|
|
if (qobject_cast<QAction*>(*it)!=a)
|
|
|
|
qobject_cast<QAction*>(*it)->setChecked(false);
|
|
|
|
_slot = (cryptoki::Slot*)a->data().toLongLong();
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
void setup() {
|
|
|
|
try {
|
|
|
|
_progress->steps(3);
|
|
|
|
slotInfo();
|
|
|
|
++*_progress;
|
|
|
|
tokenInfo();
|
|
|
|
++*_progress;
|
|
|
|
certificates();
|
|
|
|
++*_progress;
|
|
|
|
objects();
|
|
|
|
} catch (...) {
|
|
|
|
_progress->reset();
|
|
|
|
on_actionRescan_triggered();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void libraryInfo(std::string lib) {
|
|
|
|
_soname->setText(qs(lib));
|
|
|
|
cryptoki::Info inf(_cryptoki->info());
|
|
|
|
_libraryCryptokiVersion->setText(QString("%1.%2")
|
|
|
|
.arg(inf.cryptokiVersion.major)
|
|
|
|
.arg(inf.cryptokiVersion.minor));
|
|
|
|
_libraryManufacturerID->setText(qs(inf.manufacturerID));
|
|
|
|
_libraryDescription->setText(qs(inf.libraryDescription));
|
|
|
|
_libraryVersion->setText(QString("%1.%2")
|
|
|
|
.arg(inf.libraryVersion.major)
|
|
|
|
.arg(inf.libraryVersion.minor));
|
|
|
|
}
|
|
|
|
void slotInfo() {
|
|
|
|
try {
|
|
|
|
if (!_slot) return;
|
|
|
|
_hardware->setTabEnabled(1, true);
|
|
|
|
cryptoki::SlotInfo slotInfo(_slot->slotinfo());
|
|
|
|
_slotDescription->setText(qs(slotInfo.slotDescription));
|
|
|
|
_slotManufacturerID->setText(qs(slotInfo.manufacturerID));
|
|
|
|
_slotHardwareVersion->setText(QString("%1.%2")
|
|
|
|
.arg(slotInfo.hardwareVersion.major)
|
|
|
|
.arg(slotInfo.hardwareVersion.minor));
|
|
|
|
_slotFirmwareVersion->setText(QString("%1.%2")
|
|
|
|
.arg(slotInfo.firmwareVersion.major)
|
|
|
|
.arg(slotInfo.firmwareVersion.minor));
|
|
|
|
_tokenPresent->setEnabled(slotInfo.flags&CKF_TOKEN_PRESENT);
|
|
|
|
_removableDevice->setEnabled(slotInfo.flags&CKF_REMOVABLE_DEVICE);
|
|
|
|
_hwSlot->setEnabled(slotInfo.flags&CKF_HW_SLOT);
|
|
|
|
} catch (...) {
|
|
|
|
_hardware->setTabEnabled(1, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void tokenInfo() {
|
|
|
|
try {
|
|
|
|
if (!_slot) return;
|
|
|
|
_hardware->setTabEnabled(2, true);
|
|
|
|
_hardware->setTabEnabled(3, true);
|
|
|
|
cryptoki::TokenInfo tokenInfo(_slot->tokeninfo());
|
|
|
|
_tokenLabel->setText(qs(tokenInfo.label));
|
|
|
|
_tokenManufacturerID->setText(qs(tokenInfo.manufacturerID));
|
|
|
|
_tokenModel->setText(qs(tokenInfo.model));
|
|
|
|
_tokenSerialNumber->setText(qs(tokenInfo.serialNumber));
|
|
|
|
_tokenSessionCount->setText(QString("%2/%1")
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.maxSessionCount)))
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.sessionCount))));
|
|
|
|
_tokenRWSessionCount->setText(QString("%2/%1")
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.maxRwSessionCount)))
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.rwSessionCount))));
|
|
|
|
_tokenPinLen->setText(QString("%2-%1")
|
|
|
|
.arg(tokenInfo.maxPinLen)
|
|
|
|
.arg(tokenInfo.minPinLen));
|
|
|
|
_tokenPublicMemory->setText(QString("%2/%1")
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.totalPublicMemory)))
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.freePublicMemory))));
|
|
|
|
_tokenPrivateMemory->setText(QString("%2/%1")
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.totalPrivateMemory)))
|
|
|
|
.arg(qs(cryptoki::string
|
|
|
|
(tokenInfo.freePrivateMemory))));
|
|
|
|
_tokenHardwareVersion->setText(QString("%1.%2")
|
|
|
|
.arg(tokenInfo.hardwareVersion.major)
|
|
|
|
.arg(tokenInfo.hardwareVersion.minor));
|
|
|
|
_tokenFirmwareVersion->setText(QString("%1.%2")
|
|
|
|
.arg(tokenInfo.firmwareVersion.major)
|
|
|
|
.arg(tokenInfo.firmwareVersion.minor));
|
|
|
|
_tokenUTCTime->setText(qs(tokenInfo.utcTime));
|
|
|
|
_tokenUTCTime->setVisible(tokenInfo.flags&CKF_CLOCK_ON_TOKEN);
|
|
|
|
_rng->setEnabled(tokenInfo.flags&CKF_RNG);
|
|
|
|
_writeProtected->setEnabled(tokenInfo.flags&CKF_WRITE_PROTECTED);
|
|
|
|
_loginRequired->setEnabled(tokenInfo.flags&CKF_LOGIN_REQUIRED);
|
|
|
|
_userPinInitialized->setEnabled
|
|
|
|
(tokenInfo.flags&CKF_USER_PIN_INITIALIZED);
|
|
|
|
_restoreKeyNotNeeded->setEnabled
|
|
|
|
(tokenInfo.flags&CKF_RESTORE_KEY_NOT_NEEDED);
|
|
|
|
_clockOnToken->setEnabled(tokenInfo.flags&CKF_CLOCK_ON_TOKEN);
|
|
|
|
_protectedAuthenticationPath->setEnabled
|
|
|
|
(tokenInfo.flags&CKF_PROTECTED_AUTHENTICATION_PATH);
|
|
|
|
_dualCryptoOperations->setEnabled
|
|
|
|
(tokenInfo.flags&CKF_DUAL_CRYPTO_OPERATIONS);
|
|
|
|
_tokenInitialized->setEnabled(tokenInfo.flags&CKF_TOKEN_INITIALIZED);
|
|
|
|
_secondaryAuthentication->setEnabled
|
|
|
|
(tokenInfo.flags&CKF_SECONDARY_AUTHENTICATION);
|
|
|
|
_userPinCountLow->setEnabled(tokenInfo.flags&CKF_USER_PIN_COUNT_LOW);
|
|
|
|
_userPinFinalTry->setEnabled(tokenInfo.flags&CKF_USER_PIN_FINAL_TRY);
|
|
|
|
_userPinLocked->setEnabled(tokenInfo.flags&CKF_USER_PIN_LOCKED);
|
|
|
|
_userPinToBeChanged->setEnabled
|
|
|
|
(tokenInfo.flags&CKF_USER_PIN_TO_BE_CHANGED);
|
|
|
|
_soPinCountLow->setEnabled(tokenInfo.flags&CKF_SO_PIN_COUNT_LOW);
|
|
|
|
_soPinFinalTry->setEnabled(tokenInfo.flags&CKF_SO_PIN_FINAL_TRY);
|
|
|
|
_soPinLocked->setEnabled(tokenInfo.flags&CKF_SO_PIN_LOCKED);
|
|
|
|
_soPinToBeChanged->setEnabled(tokenInfo.flags&CKF_SO_PIN_TO_BE_CHANGED);
|
|
|
|
} catch (...) {
|
|
|
|
_hardware->setTabEnabled(2, false);
|
|
|
|
_hardware->setTabEnabled(3, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void certificates() {
|
|
|
|
try {
|
|
|
|
_certificates->clear();
|
|
|
|
if (!_slot) return;
|
|
|
|
_certificates->setEnabled(true);
|
|
|
|
cryptoki::Session session(*_slot);
|
|
|
|
cryptoki::ObjectList certs
|
|
|
|
(session.find(cryptoki::Attribute(CKA_CLASS)
|
|
|
|
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)));
|
|
|
|
_progress->steps(certs.size());
|
|
|
|
for (cryptoki::ObjectList::iterator cert(certs.begin());
|
|
|
|
cert!=certs.end(); ++cert) {
|
|
|
|
std::string data(cert->attribute(CKA_VALUE).value);
|
|
|
|
QByteArray der(QByteArray(data.data(), data.size()));
|
|
|
|
QSslCertificate c(der, QSsl::Der);
|
|
|
|
addCertificate(cert->attribute(CKA_LABEL).value,
|
|
|
|
crypto::hex(cert->attribute(CKA_ID).value), c);
|
|
|
|
++*_progress;
|
|
|
|
}
|
|
|
|
} catch (...) {
|
|
|
|
_certificates->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void objects() {
|
|
|
|
try {
|
|
|
|
_objects->clear();
|
|
|
|
if (!_slot) return;
|
|
|
|
_objects->setEnabled(true);
|
|
|
|
cryptoki::Session session(*_slot);
|
|
|
|
cryptoki::ObjectList objs(session.find());
|
|
|
|
_progress->steps(objs.size());
|
|
|
|
for (cryptoki::ObjectList::iterator obj(objs.begin());
|
|
|
|
obj!=objs.end(); ++obj) {
|
|
|
|
_objects->addTopLevelItem
|
|
|
|
(new QTreeWidgetItem
|
|
|
|
(QStringList()
|
|
|
|
<<qs(obj->attribute(CKA_LABEL).value)
|
|
|
|
<<qs(crypto::hex(obj->attribute(CKA_ID).value))));
|
|
|
|
++*_progress;
|
|
|
|
}
|
|
|
|
_objects->resizeColumnToContents(0);
|
|
|
|
_objects->resizeColumnToContents(1);
|
|
|
|
} catch (...) {
|
|
|
|
_objects->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void addCertificate(const std::string& label, const std::string& id,
|
|
|
|
const QSslCertificate& cert) {
|
|
|
|
if (cert.isNull()) return;
|
|
|
|
QTreeWidgetItem* c(new QTreeWidgetItem(QStringList()<<qs(label)));
|
|
|
|
c->setData(0, Qt::UserRole, qs(id));
|
|
|
|
_certificates->addTopLevelItem(c);
|
|
|
|
c->addChild
|
|
|
|
((new QTreeWidgetItem
|
|
|
|
(QStringList()<<tr("Valid Since")
|
|
|
|
<<cert.effectiveDate().toString(Qt::SystemLocaleLongDate))));
|
|
|
|
c->addChild
|
|
|
|
((new QTreeWidgetItem
|
|
|
|
(QStringList()<<tr("Valid Until")
|
|
|
|
<<cert.expiryDate().toString(Qt::SystemLocaleLongDate))));
|
|
|
|
c->addChild
|
|
|
|
((new QTreeWidgetItem
|
|
|
|
(QStringList()<<tr("Certificate Serial Number")
|
|
|
|
<<cert.serialNumber())));
|
|
|
|
QTreeWidgetItem *it(0);
|
|
|
|
c->addChild
|
|
|
|
((it = new QTreeWidgetItem(QStringList()<<tr("Subject Info")<<"")));
|
|
|
|
for (QSslCertificate::SubjectInfo
|
|
|
|
si(QSslCertificate::StateOrProvinceName);
|
|
|
|
si>=QSslCertificate::Organization;
|
|
|
|
si=(QSslCertificate::SubjectInfo)((int)si-1))
|
|
|
|
if (!cert.subjectInfo(si).isEmpty()) {
|
|
|
|
it->addChild
|
|
|
|
((new QTreeWidgetItem(subjectInfo(si)
|
|
|
|
<<utfConv(cert.subjectInfo(si)))));
|
|
|
|
}
|
|
|
|
it->setExpanded(true);
|
|
|
|
QMultiMap<QSsl::AlternateNameEntryType, QString>
|
|
|
|
#if QT_VERSION <0x050000
|
|
|
|
asns(cert.alternateSubjectNames())
|
|
|
|
#else
|
|
|
|
asns(cert.subjectAlternativeNames())
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
for (QMultiMap<QSsl::AlternateNameEntryType, QString>::iterator
|
|
|
|
asn(asns.begin()); asn!=asns.end(); ++asn)
|
|
|
|
it->addChild
|
|
|
|
((new QTreeWidgetItem
|
|
|
|
(QStringList()<<alternateName(asn.key())<<asn.value())));
|
|
|
|
c->addChild
|
|
|
|
((it = new QTreeWidgetItem(QStringList()<<tr("Issuer Info")<<"")));
|
|
|
|
for (QSslCertificate::SubjectInfo
|
|
|
|
si(QSslCertificate::StateOrProvinceName);
|
|
|
|
si>=QSslCertificate::Organization;
|
|
|
|
si=(QSslCertificate::SubjectInfo)((int)si-1))
|
|
|
|
if (!cert.issuerInfo(si).isEmpty())
|
|
|
|
it->addChild
|
|
|
|
((new QTreeWidgetItem(subjectInfo(si)
|
|
|
|
<<utfConv(cert.issuerInfo(si)))));
|
|
|
|
it->setExpanded(true);
|
|
|
|
_certificates->resizeColumnToContents(0);
|
|
|
|
_certificates->resizeColumnToContents(1);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
void deleteCert(QTreeWidgetItem* item) {
|
|
|
|
if (!_slot) return;
|
|
|
|
if (_pin->text().isEmpty()) {
|
|
|
|
QMessageBox::critical(this, tr("PIN required"), tr("Please enter PIN"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (item->parent()) return deleteCert(item->parent());
|
|
|
|
QByteArray qid(QByteArray::fromHex(item->data(0, Qt::UserRole)
|
|
|
|
.toByteArray()));
|
|
|
|
std::string id(qid.data(), qid.size());
|
|
|
|
cryptoki::Session session(*_slot, true);
|
|
|
|
try {
|
|
|
|
session.login(_pin->text().toStdString());
|
|
|
|
} catch (...) {
|
|
|
|
QMessageBox::critical(this, tr("Login Failed"), tr("Wrong PIN"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cryptoki::ObjectList objs
|
|
|
|
(session.find(cryptoki::AttributeList()
|
|
|
|
<<cryptoki::Attribute(CKA_CLASS)
|
|
|
|
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)
|
|
|
|
<<cryptoki::Attribute(CKA_ID, id)));
|
|
|
|
for (cryptoki::ObjectList::iterator obj(objs.begin());
|
|
|
|
obj!=objs.end(); ++obj) try {
|
|
|
|
obj->destroy();
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
QMessageBox::critical(this, tr("Delete Failed"),
|
|
|
|
tr("Certificate Deletion Failes"));
|
|
|
|
}
|
|
|
|
setup();
|
|
|
|
}
|
|
|
|
QString alternateName(QSsl::AlternateNameEntryType an) {
|
|
|
|
switch (an) {
|
|
|
|
case QSsl::EmailEntry: return tr("E-Mail");
|
|
|
|
case QSsl::DnsEntry: return tr("URL");
|
|
|
|
}
|
|
|
|
return tr("error", "unknown certificate subject alternate name");
|
|
|
|
}
|
|
|
|
QStringList subjectInfo(QSslCertificate::SubjectInfo si) {
|
|
|
|
QStringList res;
|
|
|
|
switch (si) {
|
|
|
|
case QSslCertificate::Organization:
|
|
|
|
res<<tr("Organization"); break;
|
|
|
|
case QSslCertificate::CommonName:
|
|
|
|
res<<tr("Common Name"); break;
|
|
|
|
case QSslCertificate::LocalityName:
|
|
|
|
res<<tr("Locality"); break;
|
|
|
|
case QSslCertificate::OrganizationalUnitName:
|
|
|
|
res<<tr("Organizational Unit"); break;
|
|
|
|
case QSslCertificate::CountryName:
|
|
|
|
res<<tr("Country"); break;
|
|
|
|
case QSslCertificate::StateOrProvinceName:
|
|
|
|
res<<tr("State or Province"); break;
|
|
|
|
default:
|
|
|
|
res<<tr("error", "unknown certificate subject info"); break;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
QString utfConv(const QString& txt) {
|
|
|
|
QByteArray value(txt.toLatin1());
|
|
|
|
for (int i(-1); (i=value.indexOf("\\x"))!=-1 && i+3<value.size();)
|
|
|
|
value.replace(i, 4, QByteArray::fromHex(value.mid(i+2, 2)));
|
|
|
|
return QString::fromUtf8(value.data(), value.size());
|
|
|
|
}
|
|
|
|
QStringList utfConv(const QStringList& txts) {
|
|
|
|
QStringList res;
|
|
|
|
Q_FOREACH(QString txt, txts) {
|
|
|
|
QByteArray value(txt.toLatin1());
|
|
|
|
for (int i(-1); (i=value.indexOf("\\x"))!=-1 && i+3<value.size();) {
|
|
|
|
value.replace(i, 4, QByteArray::fromHex(value.mid(i+2, 2)));
|
|
|
|
res<<QString::fromUtf8(value.data(), value.size());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
std::auto_ptr<cryptoki::Library> _cryptoki;
|
|
|
|
cryptoki::SlotList _slotList;
|
|
|
|
cryptoki::Slot* _slot;
|
|
|
|
Progress* _progress;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|