mirror of
https://github.com/chris2511/xca.git
synced 2026-09-12 19:51:05 +05:00
This is a large squash of many small commits. Allow porting data from the legacy format to SQL. Store Binaries base64 encoded and use db->transaction Update password hash to be 8000 x SHA512 with 8 byte Salt Add revocations table and fixup CRL generation Add comment and insertion date columns Fix column saving, remove trust, add XcaDialog Allow changing the internal name and comment in Cert/Req details view Extend Comment functionality, Replace About.ui by XcaDialog.ui
322 lines
7.0 KiB
C++
322 lines
7.0 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 "lib/pkcs11.h"
|
|
#include "distname.h"
|
|
#include "clicklabel.h"
|
|
#include "ItemCombo.h"
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QLineEdit>
|
|
#include <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].toLatin1());
|
|
if (nid == NID_undef)
|
|
return -3;
|
|
defaultEcNid = nid;
|
|
} else {
|
|
size = sl[1].toInt();
|
|
if (size <= 0)
|
|
return -4;
|
|
defaultSize = size;
|
|
}
|
|
defaultType = type;
|
|
return 0;
|
|
}
|