mirror of
https://github.com/chris2511/xca.git
synced 2026-09-12 19:51:05 +05:00
321 lines
7.1 KiB
C++
321 lines
7.1 KiB
C++
/* vi: set sw=4 ts=4:
|
|
*
|
|
* Copyright (C) 2001 - 2014 Christian Hohnstaedt.
|
|
*
|
|
* All rights reserved.
|
|
*/
|
|
|
|
|
|
#include "NewKey.h"
|
|
#include "MainWindow.h"
|
|
#include "lib/pki_evp.h"
|
|
#include "widgets/distname.h"
|
|
#include "widgets/clicklabel.h"
|
|
#include "lib/pkcs11.h"
|
|
#include <QtGui/QLabel>
|
|
#include <QtGui/QPushButton>
|
|
#include <QtGui/QLineEdit>
|
|
#include <QtCore/QStringList>
|
|
|
|
struct typelist {
|
|
const char *name;
|
|
int type;
|
|
};
|
|
|
|
static const struct typelist typeList[] = {
|
|
{ "RSA", EVP_PKEY_RSA },
|
|
{ "DSA", EVP_PKEY_DSA },
|
|
#ifndef OPENSSL_NO_EC
|
|
{ "EC", EVP_PKEY_EC },
|
|
#endif
|
|
};
|
|
|
|
int NewKey::defaultType = EVP_PKEY_RSA;
|
|
int NewKey::defaultEcNid = NID_undef;
|
|
int NewKey::defaultSize = 2048;
|
|
|
|
class keyListItem
|
|
{
|
|
protected:
|
|
const struct typelist *tl;
|
|
|
|
public:
|
|
bool card;
|
|
QString printname;
|
|
slotid slot;
|
|
unsigned minKeySize;
|
|
unsigned maxKeySize;
|
|
unsigned long ec_flags;
|
|
|
|
keyListItem(pkcs11 *p11, slotid nslot, CK_MECHANISM_TYPE m)
|
|
{
|
|
slot = nslot;
|
|
CK_MECHANISM_INFO mechinfo;
|
|
p11->mechanismInfo(slot, m, &mechinfo);
|
|
|
|
minKeySize = mechinfo.ulMinKeySize;
|
|
maxKeySize = mechinfo.ulMaxKeySize;
|
|
if (maxKeySize == 0) {
|
|
/* Fallback for libraries not filling in the maxKeySize */
|
|
maxKeySize = INT_MAX;
|
|
}
|
|
tkInfo ti = p11->tokenInfo(slot);
|
|
switch (m) {
|
|
case CKM_RSA_PKCS_KEY_PAIR_GEN:
|
|
tl = typeList; //idx of EVP_PKEY_RSA
|
|
break;
|
|
case CKM_DSA_KEY_PAIR_GEN:
|
|
tl = typeList +1;
|
|
break;
|
|
#ifndef OPENSSL_NO_EC
|
|
case CKM_EC_KEY_PAIR_GEN:
|
|
tl = typeList +2;
|
|
CK_MECHANISM_INFO info;
|
|
p11->mechanismInfo(slot, m, &info);
|
|
ec_flags = info.flags & (CKF_EC_F_P | CKF_EC_F_2M);
|
|
if (!ec_flags) {
|
|
/* Fallback: Assume to support both for
|
|
* libraries leaving this flag empty
|
|
*/
|
|
ec_flags = CKF_EC_F_P | CKF_EC_F_2M;
|
|
}
|
|
#endif
|
|
}
|
|
printname = QString("%1 #%2 (%3 Key of %4 - %5 bits)").
|
|
arg(ti.label()).arg(ti.serial()).
|
|
arg(tl->name).
|
|
arg(minKeySize).
|
|
arg(maxKeySize);
|
|
card = true;
|
|
}
|
|
keyListItem(const struct typelist *t=typeList)
|
|
{
|
|
tl = t;
|
|
printname = QString(tl->name);
|
|
card = false;
|
|
slot = slotid();
|
|
minKeySize = 0;
|
|
maxKeySize = INT_MAX;
|
|
ec_flags = 0;
|
|
}
|
|
keyListItem(const keyListItem &k)
|
|
{
|
|
tl = k.tl;
|
|
printname = k.printname;
|
|
card = k.card;
|
|
slot = k.slot;
|
|
minKeySize = k.minKeySize;
|
|
maxKeySize = k.maxKeySize;
|
|
ec_flags = k.ec_flags;
|
|
}
|
|
int type()
|
|
{
|
|
return tl->type;
|
|
}
|
|
QString typeName()
|
|
{
|
|
return QString(tl->name);
|
|
}
|
|
};
|
|
|
|
Q_DECLARE_METATYPE(keyListItem);
|
|
|
|
NewKey::NewKey(QWidget *parent, QString name)
|
|
:QDialog(parent)
|
|
{
|
|
static const char* const sizeList[] = { "1024", "2048", "4096" };
|
|
size_t i;
|
|
slotidList p11_slots;
|
|
QList<keyListItem> keytypes;
|
|
|
|
setupUi(this);
|
|
setWindowTitle(tr(XCA_TITLE));
|
|
image->setPixmap(*MainWindow::keyImg);
|
|
|
|
if (!name.isEmpty())
|
|
keyDesc->setText(name);
|
|
|
|
keyLength->setEditable(true);
|
|
for (i=0; i < ARRAY_SIZE(sizeList); i++ ) {
|
|
keyLength->addItem(QString(sizeList[i]) + " bit");
|
|
}
|
|
for (i=0; i < ARRAY_SIZE(typeList); i++ ) {
|
|
keyListItem gk(typeList +i);
|
|
keytypes << gk;
|
|
}
|
|
updateCurves();
|
|
keyLength->setEditText(QString::number(defaultSize) + " bit");
|
|
keyDesc->setFocus();
|
|
if (pkcs11::loaded()) try {
|
|
pkcs11 p11;
|
|
p11_slots = p11.getSlotList();
|
|
|
|
foreach(slotid slot, p11_slots) {
|
|
QList<CK_MECHANISM_TYPE> ml = p11.mechanismList(slot);
|
|
if (ml.contains(CKM_RSA_PKCS_KEY_PAIR_GEN)) {
|
|
keyListItem tk(&p11, slot, CKM_RSA_PKCS_KEY_PAIR_GEN);
|
|
keytypes << tk;
|
|
}
|
|
if (ml.contains(CKM_DSA_KEY_PAIR_GEN)) {
|
|
keyListItem tk(&p11, slot, CKM_DSA_KEY_PAIR_GEN);
|
|
keytypes << tk;
|
|
}
|
|
#ifndef OPENSSL_NO_EC
|
|
if (ml.contains(CKM_EC_KEY_PAIR_GEN)) {
|
|
keyListItem tk(&p11, slot, CKM_EC_KEY_PAIR_GEN);
|
|
keytypes << tk;
|
|
}
|
|
#endif
|
|
}
|
|
} catch (errorEx &err) {
|
|
p11_slots.clear();
|
|
}
|
|
for (int i=0; i<keytypes.count(); i++) {
|
|
QVariant q;
|
|
q.setValue(keytypes[i]);
|
|
keyType->addItem(keytypes[i].printname, q);
|
|
if (!keytypes[i].card && keytypes[i].type() == defaultType)
|
|
keyType->setCurrentIndex(i);
|
|
}
|
|
buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create"));
|
|
}
|
|
|
|
void NewKey::updateCurves(unsigned min, unsigned max, unsigned long ec_flags)
|
|
{
|
|
#ifndef OPENSSL_NO_EC
|
|
QString ec_default;
|
|
QStringList curve_x962, curve_other;
|
|
foreach(builtin_curve curve, pki_key::builtinCurves) {
|
|
const char *sn = OBJ_nid2sn(curve.nid);
|
|
QString comment = curve.comment;
|
|
|
|
if (!sn || curve.order_size < min || curve.order_size > max)
|
|
continue;
|
|
if (ec_flags) {
|
|
if ((curve.type & ec_flags) == 0)
|
|
continue;
|
|
}
|
|
if (comment.isEmpty())
|
|
comment = "---";
|
|
QString p = QString(sn) + ": " + comment;
|
|
if (curve.nid == defaultEcNid)
|
|
ec_default = p;
|
|
switch (curve.flags) {
|
|
case CURVE_X962: curve_x962 << p; break;
|
|
case CURVE_OTHER: curve_other << p; break;
|
|
}
|
|
}
|
|
curveBox->clear();
|
|
curveBox->addItems(curve_x962);
|
|
curveBox->addItems(curve_other);
|
|
curveBox->setCurrentIndex(curveBox->findText(ec_default));
|
|
if (curveBox->currentIndex() == -1)
|
|
curveBox->setCurrentIndex(0);
|
|
#else
|
|
(void)min; (void)max; (void)ec_flags;
|
|
#endif
|
|
}
|
|
|
|
void NewKey::on_keyType_currentIndexChanged(int idx)
|
|
{
|
|
bool curve_enabled;
|
|
keyListItem ki = keyType->itemData(idx).value<keyListItem>();
|
|
|
|
curve_enabled = (ki.type() == EVP_PKEY_EC);
|
|
curveBox->setVisible(curve_enabled);
|
|
curveLabel->setVisible(curve_enabled);
|
|
keySizeLabel->setVisible(!curve_enabled);
|
|
keyLength->setVisible(!curve_enabled);
|
|
|
|
rememberDefault->setEnabled(!ki.card);
|
|
if (curve_enabled && ki.card) {
|
|
updateCurves(ki.minKeySize, ki.maxKeySize, ki.ec_flags);
|
|
}
|
|
}
|
|
|
|
static keyListItem currentKey(QComboBox *keyType)
|
|
{
|
|
QVariant q = keyType->itemData(keyType->currentIndex());
|
|
return q.value<keyListItem>();
|
|
}
|
|
|
|
int NewKey::getKeytype()
|
|
{
|
|
return currentKey(keyType).type();
|
|
}
|
|
|
|
int NewKey::getKeysize()
|
|
{
|
|
if (getKeytype() == EVP_PKEY_EC)
|
|
return -1;
|
|
QString size = keyLength->currentText();
|
|
size.replace(QRegExp("[^0-9]"), "");
|
|
return size.toInt();
|
|
}
|
|
|
|
int NewKey::getKeyCurve_nid()
|
|
{
|
|
if (getKeytype() != EVP_PKEY_EC)
|
|
return NID_undef;
|
|
QString desc = curveBox->currentText();
|
|
desc.replace(QRegExp("^(X9.62) "), "");
|
|
desc.replace(QRegExp(":.*"), "");
|
|
return OBJ_sn2nid(CCHAR(desc));
|
|
}
|
|
|
|
bool NewKey::isToken()
|
|
{
|
|
keyListItem k = currentKey(keyType);
|
|
return k.card;
|
|
}
|
|
|
|
slotid NewKey::getKeyCardSlot()
|
|
{
|
|
keyListItem k = currentKey(keyType);
|
|
return k.slot;
|
|
}
|
|
|
|
QString NewKey::getAsString()
|
|
{
|
|
keyListItem k = currentKey(keyType);
|
|
QString data;
|
|
|
|
if (k.card)
|
|
return QString();
|
|
if (k.type() == EVP_PKEY_EC) {
|
|
data = OBJ_obj2QString(OBJ_nid2obj(getKeyCurve_nid()), 1);
|
|
} else {
|
|
data = QString::number(getKeysize());
|
|
}
|
|
return QString("%1:%2").arg(currentKey(keyType).typeName()).arg(data);
|
|
}
|
|
|
|
int NewKey::setDefault(QString def)
|
|
{
|
|
int type = -1, size = 0, nid = NID_undef;
|
|
QStringList sl = def.split(':');
|
|
|
|
if (sl.size() != 2)
|
|
return -1;
|
|
for (unsigned i=0; i < ARRAY_SIZE(typeList); i++ ) {
|
|
if (sl[0] == typeList[i].name) {
|
|
type = typeList[i].type;
|
|
}
|
|
}
|
|
if (type == -1)
|
|
return -2;
|
|
if (type == EVP_PKEY_EC) {
|
|
nid = OBJ_txt2nid(sl[1].toAscii());
|
|
if (nid == NID_undef)
|
|
return -3;
|
|
defaultEcNid = nid;
|
|
} else {
|
|
size = sl[1].toInt();
|
|
if (size <= 0)
|
|
return -4;
|
|
defaultSize = size;
|
|
}
|
|
defaultType = type;
|
|
return 0;
|
|
}
|