From 8aa514107823e9d313e8cb943b94d2e8a1ab60df Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Thu, 13 Nov 2014 20:07:44 +0100 Subject: [PATCH] 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 --- lib/pki_evp.cpp | 25 -------------------- lib/pki_evp.h | 1 - lib/pki_key.cpp | 26 +++++++++++++++++++++ lib/pki_key.h | 5 +--- lib/pki_scard.cpp | 51 +++++++++++++++++++++++++++++------------ lib/pki_scard.h | 1 + lib/pki_x509.cpp | 2 ++ ui/Options.ui | 12 ++++++++++ widgets/MW_database.cpp | 4 ++++ widgets/MW_menu.cpp | 10 +++++++- 10 files changed, 91 insertions(+), 46 deletions(-) diff --git a/lib/pki_evp.cpp b/lib/pki_evp.cpp index d4f26078..4d4a6272 100644 --- a/lib/pki_evp.cpp +++ b/lib/pki_evp.cpp @@ -164,31 +164,6 @@ static bool EVP_PKEY_isPrivKey(EVP_PKEY *key) return false; } -QList pki_evp::possibleHashNids() -{ - QList 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) { diff --git a/lib/pki_evp.h b/lib/pki_evp.h index f52af4f0..57b59621 100644 --- a/lib/pki_evp.h +++ b/lib/pki_evp.h @@ -46,7 +46,6 @@ class pki_evp: public pki_key /* destructor */ virtual ~pki_evp(); - QList possibleHashNids(); EVP_PKEY *priv2pub(EVP_PKEY* key); static QString removeTypeFromIntName(QString n); void fromPEM_BIO(BIO *bio, QString name); diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index 190665b7..3c84aa72 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -263,6 +263,32 @@ QString pki_key::ecPubKey() return pub; } #endif + +QList pki_key::possibleHashNids() +{ + QList 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; diff --git a/lib/pki_key.h b/lib/pki_key.h index 67fe22eb..5178fbf4 100644 --- a/lib/pki_key.h +++ b/lib/pki_key.h @@ -55,10 +55,7 @@ class pki_key: public pki_base virtual bool isToken(); virtual QString getTypeString(void) const; virtual QString getIntNameWithType(void); - virtual QList possibleHashNids() - { - return QList(); - } + virtual QList possibleHashNids(); virtual QString getMsg(msg_type msg); virtual QString length(); diff --git a/lib/pki_scard.cpp b/lib/pki_scard.cpp index 42ae73f9..3a154dae 100644 --- a/lib/pki_scard.cpp +++ b/lib/pki_scard.cpp @@ -28,6 +28,7 @@ #include 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 pki_scard::possibleHashNids() { QList 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; } diff --git a/lib/pki_scard.h b/lib/pki_scard.h index 9f440bc9..9bb280a7 100644 --- a/lib/pki_scard.h +++ b/lib/pki_scard.h @@ -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); diff --git a/lib/pki_x509.cpp b/lib/pki_x509.cpp index 6ed43a32..171047b5 100644 --- a/lib/pki_x509.cpp +++ b/lib/pki_x509.cpp @@ -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(); } diff --git a/ui/Options.ui b/ui/Options.ui index 62f7d00d..f05fcee4 100644 --- a/ui/Options.ui +++ b/ui/Options.ui @@ -103,6 +103,18 @@ + + + + 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. + + + Only use hashes supported by the token when signing with a token key + + + diff --git a/widgets/MW_database.cpp b/widgets/MW_database.cpp index 05f47a57..b2ef89eb 100644 --- a/widgets/MW_database.cpp +++ b/widgets/MW_database.cpp @@ -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)); diff --git a/widgets/MW_menu.cpp b/widgets/MW_menu.cpp index 679b0ebf..719585f7 100644 --- a/widgets/MW_menu.cpp +++ b/widgets/MW_menu.cpp @@ -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(","); }