Optionally allow hash algos not supported by the token

Especially EC and DSA signatures are only defined
with SHA1 in PKCS#11 v2.20 spec
This commit is contained in:
Christian Hohnstaedt 2014-11-13 20:07:44 +01:00
parent a97b8f9add
commit 8aa5141078
10 changed files with 91 additions and 46 deletions

View File

@ -164,31 +164,6 @@ static bool EVP_PKEY_isPrivKey(EVP_PKEY *key)
return false;
}
QList<int> pki_evp::possibleHashNids()
{
QList<int> nids;
switch (EVP_PKEY_type(key->type)) {
case EVP_PKEY_RSA:
nids << NID_md5 << NID_sha1 << NID_sha256 <<
NID_sha384 << NID_sha512 << NID_ripemd160;
break;
case EVP_PKEY_DSA:
nids << NID_sha1;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
nids << NID_sha256;
#endif
break;
case EVP_PKEY_EC:
nids << NID_sha1;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
nids << NID_sha256 << NID_sha384 << NID_sha512;
#endif
break;
}
return nids;
};
void pki_evp::openssl_pw_error(QString fname)
{
switch (ERR_peek_error() & 0xff000fff) {

View File

@ -46,7 +46,6 @@ class pki_evp: public pki_key
/* destructor */
virtual ~pki_evp();
QList<int> possibleHashNids();
EVP_PKEY *priv2pub(EVP_PKEY* key);
static QString removeTypeFromIntName(QString n);
void fromPEM_BIO(BIO *bio, QString name);

View File

@ -263,6 +263,32 @@ QString pki_key::ecPubKey()
return pub;
}
#endif
QList<int> pki_key::possibleHashNids()
{
QList<int> nids;
switch (EVP_PKEY_type(key->type)) {
case EVP_PKEY_RSA:
nids << NID_md5 << NID_sha1 << NID_sha256 <<
NID_sha384 << NID_sha512 << NID_ripemd160;
break;
case EVP_PKEY_DSA:
nids << NID_sha1;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
nids << NID_sha256;
#endif
break;
case EVP_PKEY_EC:
nids << NID_sha1;
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
nids << NID_sha256 << NID_sha384 << NID_sha512;
#endif
break;
}
return nids;
};
bool pki_key::compare(pki_base *ref)
{
pki_key *kref = (pki_key *)ref;

View File

@ -55,10 +55,7 @@ class pki_key: public pki_base
virtual bool isToken();
virtual QString getTypeString(void) const;
virtual QString getIntNameWithType(void);
virtual QList<int> possibleHashNids()
{
return QList<int>();
}
virtual QList<int> possibleHashNids();
virtual QString getMsg(msg_type msg);
virtual QString length();

View File

@ -28,6 +28,7 @@
#include <ltdl.h>
QPixmap *pki_scard::icon[1] = { NULL };
bool pki_scard::only_token_hashes = false;
void pki_scard::init(void)
{
@ -437,25 +438,45 @@ void pki_scard::store_token(slotid slot, EVP_PKEY *pkey)
QList<int> pki_scard::possibleHashNids()
{
QList<int> nids;
int i;
for (i=0; i< mech_list.count(); i++) {
switch (mech_list[i]) {
case CKM_MD5_RSA_PKCS: nids << NID_md5; break;
case CKM_DSA_SHA1:
#ifndef OPENSSL_NO_EC
case CKM_ECDSA_SHA1:
#endif
case CKM_SHA1_RSA_PKCS: nids << NID_sha1; break;
case CKM_SHA256_RSA_PKCS: nids << NID_sha256; break;
case CKM_SHA384_RSA_PKCS: nids << NID_sha384; break;
case CKM_SHA512_RSA_PKCS: nids << NID_sha512; break;
case CKM_RIPEMD160_RSA_PKCS: nids << NID_ripemd160; break;
if (!only_token_hashes)
return pki_key::possibleHashNids();
foreach(CK_MECHANISM_TYPE mechanism, mech_list) {
switch (EVP_PKEY_type(key->type)) {
case EVP_PKEY_RSA:
switch (mechanism) {
case CKM_MD5_RSA_PKCS: nids << NID_md5; break;
case CKM_SHA1_RSA_PKCS: nids << NID_sha1; break;
case CKM_SHA256_RSA_PKCS: nids << NID_sha256; break;
case CKM_SHA384_RSA_PKCS: nids << NID_sha384; break;
case CKM_SHA512_RSA_PKCS: nids << NID_sha512; break;
case CKM_RIPEMD160_RSA_PKCS: nids << NID_ripemd160; break;
}
break;
case EVP_PKEY_DSA:
switch (mechanism) {
case CKM_DSA_SHA1: nids << NID_sha1; break;
}
break;
case EVP_PKEY_EC:
switch (mechanism) {
case CKM_ECDSA_SHA1: nids << NID_sha1; break;
}
break;
}
}
if (nids.count() == 0) {
nids << NID_md5 << NID_sha1 << NID_sha256 <<
NID_sha384 << NID_sha512 << NID_ripemd160;
switch (EVP_PKEY_type(key->type)) {
case EVP_PKEY_RSA:
nids << NID_md5 << NID_sha1 << NID_sha256 <<
NID_sha384 << NID_sha512 << NID_ripemd160;
break;
case EVP_PKEY_DSA:
case EVP_PKEY_EC:
nids << NID_sha1;
break;
}
}
return nids;
}

View File

@ -32,6 +32,7 @@ class pki_scard: public pki_key
pki_scard(const QString name);
virtual ~pki_scard();
static QPixmap *icon[1];
static bool only_token_hashes;
void load_token(pkcs11 &p11, CK_OBJECT_HANDLE object);
bool prepare_card(slotid *slot, bool verifyPubkey=true) const;
void fromData(const unsigned char *p, db_header_t *head);

View File

@ -491,6 +491,7 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head)
QByteArray ba((const char*)p, size);
d2i(ba);
pki_openssl_error();
trust = db::intFromData(ba);
isrevoked = db::boolFromData(ba);
revoked.d2i(ba);
@ -510,6 +511,7 @@ void pki_x509::fromData(const unsigned char *p, db_header_t *head)
if (ba.count() > 0) {
my_error(tr("Wrong Size %1").arg(ba.count()));
}
pki_openssl_error();
}

View File

@ -103,6 +103,18 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="onlyTokenHashes">
<property name="toolTip">
<string>The hashing functionality of the token is not used by XCA.
It may however honor a restricted hash-set propagated by the token.
Especially EC and DSA are only defined with SHA1 in the PKCS#11 specification.</string>
</property>
<property name="text">
<string>Only use hashes supported by the token when signing with a token key</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">

View File

@ -44,6 +44,10 @@ int MainWindow::init_database()
mandatory_dn = "";
explicit_dn = explicit_dn_default;
pki_base::suppress_messages = false;
pki_x509::dont_colorize_expiries = false;
db_x509name::translate_dn = false;
pki_scard::only_token_hashes = false;
string_opt = QString("MASK:0x2002");
ASN1_STRING_set_default_mask_asc((char*)CCHAR(string_opt));

View File

@ -200,6 +200,8 @@ void MainWindow::setOptions()
pki_x509::dont_colorize_expiries ? Qt::Checked : Qt::Unchecked);
opt->transDnEntries->setCheckState(
db_x509name::translate_dn ? Qt::Checked : Qt::Unchecked);
opt->onlyTokenHashes->setCheckState(
pki_scard::only_token_hashes ? Qt::Checked : Qt::Unchecked);
if (!opt->exec()) {
delete opt;
@ -231,6 +233,7 @@ void MainWindow::setOptions()
pki_base::suppress_messages = opt->suppress->checkState();
pki_x509::dont_colorize_expiries = opt->noColorize->checkState();
db_x509name::translate_dn = opt->transDnEntries->checkState();
pki_scard::only_token_hashes = opt->onlyTokenHashes->checkState();
if (flags != getOptFlags()) {
flags = getOptFlags();
@ -290,6 +293,7 @@ void MainWindow::setOptFlags(QString flags)
pki_base::suppress_messages = false;
pki_x509::dont_colorize_expiries = false;
db_x509name::translate_dn = false;
pki_scard::only_token_hashes = false;
foreach(QString flag, flags.split(",")) {
if (flag == "suppress_messages")
@ -298,6 +302,8 @@ void MainWindow::setOptFlags(QString flags)
pki_x509::dont_colorize_expiries = true;
else if (flag == "translate_dn")
db_x509name::translate_dn = true;
else if (flag == "only_token_hashes")
pki_scard::only_token_hashes = true;
else if (!flag.isEmpty())
fprintf(stderr, "Unkown flag '%s'\n", CCHAR(flag));
}
@ -312,6 +318,8 @@ QString MainWindow::getOptFlags()
if (pki_x509::dont_colorize_expiries)
flags << "dont_colorize_expiries";
if (db_x509name::translate_dn)
flags += "translate_dn";
flags << "translate_dn";
if (pki_scard::only_token_hashes)
flags << "only_token_hashes";
return flags.join(",");
}