Close #477: paste an encrypted private key results in a crash

Improve error- and password handling:
 - Also identify: (ERR_LIB_PROV:PROV_R_BAD_DECRYPT) as password error.
 - Do not use the OpenSSL internal bitfield definition (0xff000fff)
   but the official API: ERR_GET_LIB(), ERR_GET_REASON()
   Especially ERR_LIB_OFFSET changed from 24 to 23 in Openssl 3.0.0
 - First check for "Cancel", then for invalid password to avoid
   an "Invalid Password" message after aborting the password input dialog.
This commit is contained in:
Christian Hohnstaedt 2023-11-02 14:06:12 +01:00
parent 8bd6141f0c
commit d29d55ab20
2 changed files with 14 additions and 5 deletions

View File

@ -22,6 +22,7 @@
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/err.h>
#include <openssl/proverr.h>
Passwd pki_evp::passwd;
@ -213,10 +214,14 @@ pki_evp::pki_evp(EVP_PKEY *pkey)
bool pki_evp::openssl_pw_error() const
{
switch (ERR_peek_error() & 0xff000fff) {
unsigned long e = ERR_peek_error();
switch (ERR_PACK(ERR_GET_LIB(e), 0, ERR_GET_REASON(e))) {
case ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_DECRYPT):
case ERR_PACK(ERR_LIB_PEM, 0, PEM_R_BAD_PASSWORD_READ):
case ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT):
case ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT):
case ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_PKCS12_CIPHERFINAL_ERROR):
pki_ign_openssl_error();
return true;
}
@ -230,14 +235,15 @@ void pki_evp::fromPEMbyteArray(const QByteArray &ba, const QString &name)
tr("Please enter the password to decrypt the private key %1.")
.arg(name));
pkey = load_ssh_ed25519_privatekey(ba, p);
pki_ign_openssl_error();
while (!pkey) {
pkey = PEM_read_bio_PrivateKey(BioByteArray(ba).ro(), NULL,
PwDialogCore::pwCallback, &p);
if (openssl_pw_error())
XCA_PASSWD_ERROR();
if (p.getResult() != pw_ok)
throw p.getResult();
if (openssl_pw_error())
XCA_PASSWD_ERROR();
if (pki_ign_openssl_error())
break;
}
@ -396,10 +402,10 @@ void pki_evp::fload(const QString &fname)
do {
pkey = PEM_read_bio_PrivateKey(BioByteArray(ba).ro(),
NULL, cb, &p);
if (openssl_pw_error())
XCA_PASSWD_ERROR();
if (p.getResult() != pw_ok)
throw p.getResult();
if (openssl_pw_error())
XCA_PASSWD_ERROR();
if (pki_ign_openssl_error())
break;
} while (!pkey);

View File

@ -127,6 +127,9 @@ void pki_multi::fromPEMbyteArray(const QByteArray &_ba, const QString &name)
XCA_ERROR(err);
delete item;
item = NULL;
} catch (...) {
delete item;
item = NULL;
}
ba.remove(0, sizeof BEGIN -1);
}