OpenSSL: Avoid all FILE pointer operations, use QFile

For interoprability reason.
To enforce it, set "#define OPENSSL_NO_STDIO 1"
All file access is done by reading/writing from/to BioByteArray()
which is filled by QFile:readAll()

Drop CRYPTO_malloc_debug / CRYPTO_mem_leaks
which is unused and disabled since many years.
This commit is contained in:
Christian Hohnstaedt 2021-11-13 23:32:57 +01:00
parent d73d4ccd51
commit 4d401792a9
18 changed files with 113 additions and 151 deletions

View File

@ -79,7 +79,6 @@ macro(guid content)
UUID GUID NAMESPACE f243d4ea-d51d-42fc-a3c0-4eb186c55d34
NAME ${content} TYPE SHA1
)
message("GUID " ${content} " " ${GUID})
endmacro()
macro(WixFile filename content)

View File

@ -9,6 +9,8 @@
#define __BASE_H
#define QT_NO_CAST_TO_ASCII 1
#define OPENSSL_NO_STDIO 1
#ifndef PACKAGE_NAME
#define XCA_TITLE "X Certificate and Key management"
#else

View File

@ -9,6 +9,7 @@
#include "dhgen.h"
#include "entropy.h"
#include "xfile.h"
#include "BioByteArray.h"
#include <openssl/rand.h>
#include <openssl/pem.h>
@ -17,19 +18,22 @@
void DHgen::run()
{
DH *dh = NULL;
BioByteArray b;
try {
dh = DH_new();
Q_CHECK_PTR(dh);
DH_generate_parameters_ex(dh, bits, 2, NULL);
openssl_error();
XFile file(fname);
file.open_write();
PEM_write_DHparams(file.fp(), dh);
PEM_write_bio_DHparams(b, dh);
openssl_error();
} catch (errorEx &e) {
err = e;
}
XFile file(fname);
file.open_write();
file.write(b);
if (dh)
DH_free(dh);
}

View File

@ -90,13 +90,13 @@ bool pki_base::visible() const
comment.contains(limitPattern);
}
void pki_base::PEM_file_comment(XFile &file) const
QByteArray pki_base::PEM_comment() const
{
if (!pem_comment)
return;
file.write(QString("XCA internal name: %1\n%2\n")
.arg(getIntName()).arg(getComment())
.toUtf8());
return QByteArray();
return QString("XCA internal name: %1\n%2\n")
.arg(getIntName()).arg(getComment()).toUtf8();
}
void pki_base::clear()

View File

@ -65,7 +65,7 @@ class pki_base : public QObject
pki_base *parent;
void my_error(const QString &error) const;
QString filename;
virtual void PEM_file_comment(XFile &file) const;
virtual QByteArray PEM_comment() const;
virtual void collect_properties(QMap<QString, QString> &) const;
QList<pki_base*> childItems;

View File

@ -132,11 +132,12 @@ void pki_crl::fload(const QString &fname)
X509_CRL *_crl;
XFile file(fname);
file.open_read();
_crl = PEM_read_X509_CRL(file.fp(), NULL, NULL, NULL);
QByteArray ba(file.readAll());
_crl = PEM_read_bio_X509_CRL(BioByteArray(ba).ro(), NULL, NULL, NULL);
if (!_crl) {
pki_ign_openssl_error();
file.retry_read();
_crl = d2i_X509_CRL_fp(file.fp(), NULL);
_crl = d2i_X509_CRL_bio(BioByteArray(ba).ro(), NULL);
}
if (pki_ign_openssl_error() || !_crl) {
if (_crl)
@ -256,13 +257,15 @@ void pki_crl::writeDefault(const QString &dirname) const
void pki_crl::writeCrl(XFile &file, bool pem) const
{
BioByteArray b;
if (pem) {
PEM_file_comment(file);
PEM_write_X509_CRL(file.fp(), crl);
b += PEM_comment();
PEM_write_bio_X509_CRL(b, crl);
} else {
i2d_X509_CRL_fp(file.fp(), crl);
i2d_X509_CRL_bio(b, crl);
}
pki_openssl_error();
file.write(b);
}
bool pki_crl::pem(BioByteArray &b)

View File

@ -389,34 +389,34 @@ void pki_evp::fload(const QString &fname)
pki_ign_openssl_error();
XFile file(fname);
file.open_read();
QByteArray ba = file.readAll();
EVP_PKEY *pkey;
do {
pkey = PEM_read_PrivateKey(file.fp(), NULL, cb, &p);
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 (pki_ign_openssl_error())
break;
file.retry_read();
} while (!pkey);
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = d2i_PrivateKey_fp(file.fp(), NULL);
pkey = d2i_PrivateKey_bio(BioByteArray(ba).ro(), NULL);
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = d2i_PKCS8PrivateKey_fp(file.fp(), NULL, cb, &p);
pkey = d2i_PKCS8PrivateKey_bio(BioByteArray(ba).ro(),
NULL, cb, &p);
}
if (!pkey) {
PKCS8_PRIV_KEY_INFO *p8inf;
pki_ign_openssl_error();
file.retry_read();
p8inf = d2i_PKCS8_PRIV_KEY_INFO_fp(file.fp(), NULL);
p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(BioByteArray(ba).ro(),
NULL);
if (p8inf) {
pkey = EVP_PKCS82PKEY(p8inf);
PKCS8_PRIV_KEY_INFO_free(p8inf);
@ -424,33 +424,27 @@ void pki_evp::fload(const QString &fname)
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = b2i_PVK_bio(file.bio(), cb, &p);
pkey = b2i_PVK_bio(BioByteArray(ba).ro(), cb, &p);
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = load_ssh_ed25519_privatekey(file.read(10000), p);
pkey = load_ssh_ed25519_privatekey(ba, p);
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = PEM_read_PUBKEY(file.fp(), NULL, cb, &p);
pkey = PEM_read_bio_PUBKEY(BioByteArray(ba).ro(), NULL, cb, &p);
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = d2i_PUBKEY_fp(file.fp(), NULL);
pkey = d2i_PUBKEY_bio(BioByteArray(ba).ro(), NULL);
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = load_ssh2_key(file);
pkey = load_ssh2_key(ba);
}
if (!pkey) {
pki_ign_openssl_error();
file.retry_read();
pkey = b2i_PublicKey_bio(file.bio());
pkey = b2i_PublicKey_bio(BioByteArray(ba).ro());
}
if (pki_ign_openssl_error() || !pkey) {
if (pkey)
@ -725,13 +719,15 @@ void pki_evp::writePKCS8(XFile &file, const EVP_CIPHER *enc,
pki_openssl_error();
return;
}
BioByteArray b;
if (pem) {
PEM_file_comment(file);
PEM_write_PKCS8PrivateKey(file.fp(), pkey, enc, NULL, 0,cb,&p);
b += PEM_comment();
PEM_write_bio_PKCS8PrivateKey(b, pkey, enc, NULL, 0, cb, &p);
} else {
i2d_PKCS8PrivateKey_fp(file.fp(), pkey, enc, NULL, 0, cb, &p);
i2d_PKCS8PrivateKey_bio(b, pkey, enc, NULL, 0, cb, &p);
}
EVP_PKEY_free(pkey);
file.write(b);
}
void pki_evp::writePVKprivate(XFile &file, pem_password_cb *cb) const
@ -747,13 +743,15 @@ void pki_evp::writePVKprivate(XFile &file, pem_password_cb *cb) const
/* In case of success! the error
* PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE)
* is set. Workaround this behavior */
if (i2b_PVK_bio(file.bio(), pkey, enc, cb, &p) == -1) {
BioByteArray b;
if (i2b_PVK_bio(b, pkey, enc, cb, &p) == -1) {
pki_openssl_error();
PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
pki_openssl_error();
}
ign_openssl_error();
EVP_PKEY_free(pkey);
file.write(b);
}
static int mycb(char *buf, int size, int, void *)
@ -799,15 +797,17 @@ void pki_evp::writeKey(XFile &file, const EVP_CIPHER *enc,
pki_openssl_error();
return;
}
BioByteArray b;
if (pem) {
PEM_file_comment(file);
PEM_write_bio_PrivateKey_traditional(file.bio(), pkey, enc,
b += PEM_comment();
PEM_write_bio_PrivateKey_traditional(b, pkey, enc,
NULL, 0, cb, &p);
} else {
i2d_PrivateKey_fp(file.fp(), pkey);
i2d_PrivateKey_bio(b, pkey);
}
EVP_PKEY_free(pkey);
pki_openssl_error();
file.write(b);
}
bool pki_evp::verify_priv(EVP_PKEY *pkey) const

View File

@ -147,7 +147,9 @@ void pki_key::writeSSH2private(XFile &file, pem_password_cb *cb) const
pki_openssl_error();
return;
}
write_SSH2_ed25519_private(file.bio(), pkey, NULL);
BioByteArray b;
write_SSH2_ed25519_private(b, pkey, NULL);
file.write(b);
}
QString pki_key::length() const
@ -406,13 +408,15 @@ bool pki_key::compare(const pki_base *ref) const
void pki_key::writePublic(XFile &file, bool pem) const
{
BioByteArray b;
if (pem) {
PEM_file_comment(file);
PEM_write_PUBKEY(file.fp(), key);
b += PEM_comment();
PEM_write_bio_PUBKEY(b, key);
} else {
i2d_PUBKEY_fp(file.fp(), key);
i2d_PUBKEY_bio(b, key);
}
pki_openssl_error();
file.write(b);
}
QString pki_key::BNoneLine(BIGNUM *bn) const
@ -589,14 +593,13 @@ QByteArray pki_key::ssh_key_next_chunk(QByteArray *ba) const
return chunk;
}
EVP_PKEY *pki_key::load_ssh2_key(XFile &file)
EVP_PKEY *pki_key::load_ssh2_key(const QByteArray &b)
{
/* See RFC 4253 Section 6.6 */
QByteArray ba;
QStringList sl;
EVP_PKEY *pk = NULL;
QByteArray ba(b);
ba = file.read(4096);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
sl = QString(ba).split(" ", Qt::SkipEmptyParts);
#else
@ -870,13 +873,12 @@ QByteArray pki_key::X509_PUBKEY_public_key() const
return data;
}
void pki_key::PEM_file_comment(XFile &file) const
QByteArray pki_key::PEM_comment() const
{
if (!pem_comment)
return;
pki_base::PEM_file_comment(file);
file.write(QString("%1 %2\n").arg(length(), getTypeString())
.toUtf8());
return QByteArray();
return pki_base::PEM_comment() +
QString("%1 %2\n").arg(length(), getTypeString()).toUtf8();
}
void pki_key::collect_properties(QMap<QString, QString> &prp) const

View File

@ -179,7 +179,7 @@ class pki_key: public pki_base
QString BNoneLine(BIGNUM *bn) const;
QByteArray SSH2publicQByteArray(bool raw=false) const;
QByteArray X509_PUBKEY_public_key() const;
void PEM_file_comment(XFile &file) const;
QByteArray PEM_comment() const;
void collect_properties(QMap<QString, QString> &prp) const;
BIGNUM *ssh_key_data2bn(QByteArray *ba) const;
@ -250,7 +250,7 @@ class pki_key: public pki_base
void d2i(QByteArray &ba);
void d2i_old(QByteArray &ba, int type);
QByteArray i2d() const;
EVP_PKEY *load_ssh2_key(XFile &file);
EVP_PKEY *load_ssh2_key(const QByteArray &ba);
void writeSSH2public(XFile &file) const;
void writeSSH2private(XFile &file, pem_password_cb *cb) const;
QString fingerprint(const QString &format) const;

View File

@ -39,7 +39,9 @@ pki_pkcs12::pki_pkcs12(const QString &fname)
setFilename(fname);
XFile file(fname);
file.open_read();
PKCS12 *pkcs12 = d2i_PKCS12_fp(file.fp(), NULL);
BioByteArray b(file.readAll());
PKCS12 *pkcs12 = d2i_PKCS12_bio(b.ro(), NULL);
if (pki_ign_openssl_error()) {
if (pkcs12)
PKCS12_free(pkcs12);
@ -139,8 +141,10 @@ void pki_pkcs12::writePKCS12(XFile &file) const
key->decryptKey(), cert->getCert(), certstack,
0, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
0, 0, 0);
i2d_PKCS12_fp(file.fp(), pkcs12);
BioByteArray b;
i2d_PKCS12_bio(b, pkcs12);
sk_X509_free(certstack);
pki_openssl_error();
PKCS12_free(pkcs12);
file.write(b);
}

View File

@ -28,7 +28,8 @@ pki_pkcs7::~pki_pkcs7()
void pki_pkcs7::encryptFile(pki_x509 *crt, const QString &filename)
{
encryptBio(crt, XFile(filename).bio());
XFile f(filename);
encryptBio(crt, BioByteArray(f.readAll()).ro());
}
void pki_pkcs7::encryptBio(pki_x509 *crt, BIO *bio)
@ -80,8 +81,10 @@ void pki_pkcs7::signBio(pki_x509 *crt, BIO *bio)
void pki_pkcs7::signFile(pki_x509 *crt, const QString &filename)
{
XFile f(filename);
f.open_read();
if (crt)
signBio(crt, XFile(filename).bio());
signBio(crt, BioByteArray(f.readAll()).ro());
}
void pki_pkcs7::signCert(pki_x509 *crt, pki_x509 *contCert)
@ -105,11 +108,13 @@ void pki_pkcs7::writeP7(XFile &file, bool PEM)
if (x)
PKCS7_add_certificate(p7, X509_dup(x->getCert()));
}
BioByteArray b;
if (PEM)
PEM_write_PKCS7(file.fp(), p7);
PEM_write_bio_PKCS7(b, p7);
else
i2d_PKCS7_fp(file.fp(), p7);
i2d_PKCS7_bio(b, p7);
openssl_error();
file.write(b);
}
void pki_pkcs7::append_certs(PKCS7 *myp7, const QString &name)
@ -168,11 +173,12 @@ void pki_pkcs7::fload(const QString &name)
PKCS7 *myp7;
XFile file(name);
file.open_read();
myp7 = PEM_read_PKCS7(file.fp(), NULL, NULL, NULL);
QByteArray ba(file.readAll());
myp7 = PEM_read_bio_PKCS7(BioByteArray(ba).ro(), NULL, NULL, NULL);
if (!myp7) {
ign_openssl_error();
file.retry_read();
myp7 = d2i_PKCS7_fp(file.fp(), NULL);
myp7 = d2i_PKCS7_bio(BioByteArray(ba).ro(), NULL);
}
if (ign_openssl_error()) {
if (myp7)

View File

@ -424,8 +424,7 @@ QByteArray pki_temp::toExportData() const
void pki_temp::writeTemp(XFile &file) const
{
PEM_file_comment(file);
file.write(toExportData());
file.write(PEM_comment() + toExportData());
}
void pki_temp::writeDefault(const QString &dirname) const

View File

@ -215,11 +215,12 @@ void pki_x509::fload(const QString &fname)
X509 *_cert;
XFile file(fname);
file.open_read();
_cert = PEM_read_X509(file.fp(), NULL, NULL, NULL);
QByteArray ba(file.readAll());
_cert = PEM_read_bio_X509(BioByteArray(ba).ro(), NULL, NULL, NULL);
if (!_cert) {
pki_ign_openssl_error();
file.retry_read();
_cert = d2i_X509_fp(file.fp(), NULL);
_cert = d2i_X509_bio(BioByteArray(ba).ro(), NULL);
}
if (pki_ign_openssl_error() || !_cert) {
if (_cert)
@ -586,13 +587,15 @@ void pki_x509::writeCert(XFile &file, bool PEM) const
{
if (!cert)
return;
BioByteArray b;
if (PEM) {
PEM_file_comment(file);
PEM_write_X509(file.fp(), cert);
b += PEM_comment();
PEM_write_bio_X509(b, cert);
} else {
i2d_X509_fp(file.fp(), cert);
i2d_X509_bio(b, cert);
}
pki_openssl_error();
file.write(b);
}
QString pki_x509::getIndexEntry()

View File

@ -171,11 +171,12 @@ void pki_x509req::fload(const QString &fname)
X509_REQ *_req;
XFile file(fname);
file.open_read();
_req = PEM_read_X509_REQ(file.fp(), NULL, NULL, NULL);
QByteArray ba(file.readAll());
_req = PEM_read_bio_X509_REQ(BioByteArray(ba).ro(), NULL, NULL, NULL);
if (!_req) {
pki_ign_openssl_error();
file.retry_read();
_req = d2i_X509_REQ_fp(file.fp(), NULL);
_req = d2i_X509_REQ_bio(BioByteArray(ba).ro(), NULL);
}
if (pki_ign_openssl_error() || !_req) {
if (_req)
@ -238,15 +239,17 @@ void pki_x509req::writeDefault(const QString &dirname) const
void pki_x509req::writeReq(XFile &file, bool pem) const
{
BioByteArray b;
if (!request)
return;
if (pem) {
PEM_file_comment(file);
PEM_write_X509_REQ(file.fp(), request);
b += PEM_comment();
PEM_write_bio_X509_REQ(b, request);
} else {
i2d_X509_REQ_fp(file.fp(), request);
i2d_X509_REQ_bio(b, request);
}
pki_openssl_error();
file.write(b);
}
bool pki_x509req::pem(BioByteArray &b)

View File

@ -296,12 +296,12 @@ bool pki_x509name::visible() const
return getSubject().search(limitPattern);
}
void pki_x509name::PEM_file_comment(XFile &file) const
QByteArray pki_x509name::PEM_comment() const
{
if (!pem_comment)
return;
pki_base::PEM_file_comment(file);
file.write(getSubject().oneLine(XN_FLAG_RFC2253).toUtf8() + "\n");
return QByteArray();
return pki_base::PEM_comment() +
getSubject().oneLine(XN_FLAG_RFC2253).toUtf8() + "\n";
}
void pki_x509name::collect_properties(QMap<QString, QString> &prp) const

View File

@ -20,7 +20,7 @@
class pki_x509name : public pki_base
{
protected:
void PEM_file_comment(XFile &file) const;
QByteArray PEM_comment() const;
public:
pki_x509name(const QString &name = QString());

View File

@ -12,14 +12,6 @@
#include <QFile>
#include <QDebug>
#include <stdio.h>
#if defined (Q_CC_MSVC)
#include <stdlib.h>
#include <io.h>
typedef int mode_t;
#else
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
@ -32,10 +24,6 @@ class XFile : public QFile
{
Q_OBJECT
private:
FILE *filp;
BIO *b;
public:
bool open(OpenMode flags)
{
@ -46,46 +34,12 @@ class XFile : public QFile
}
return o;
}
XFile(const QString &name) : QFile(name), filp(NULL), b(NULL)
XFile(const QString &name) : QFile(name)
{
}
BIO *bio()
{
if (!b)
b = BIO_new_fp(fp(), BIO_NOCLOSE);
return b;
}
FILE *fp(const char *mode = NULL)
{
if (!filp) {
if (!mode)
mode = openMode() & WriteOnly ?
"ab" : "rb";
filp = fdopen(dup(handle()), mode);
Q_CHECK_PTR(filp);
}
qDebug() << fileName() << "FILE ptr @" << ftell(filp);
return filp;
}
qint64 writeData(const char *data, qint64 maxSize)
{
if (filp)
fflush(filp);
flush();
seek(size());
qDebug() << "WriteData to" << fileName() <<
maxSize << "@" << size();
qint64 r = QFile::writeData(data, maxSize);
flush();
if (filp)
fseek(filp, 0, SEEK_END);
return r;
}
void retry_read()
{
seek(0);
if (filp)
fseek(filp, 0, SEEK_SET);
if (error()) {
throw errorEx(
tr("Error rewinding file: '%1': %2")
@ -108,13 +62,6 @@ class XFile : public QFile
{
return open(ReadOnly);
}
~XFile() {
if (filp)
fclose(filp);
if (b)
BIO_free(b);
}
};
#endif

View File

@ -6,7 +6,6 @@
*/
//#define MDEBUG
#include "MainWindow.h"
#include "XcaApplication.h"
#include "ImportMulti.h"
@ -102,12 +101,6 @@ MainWindow::MainWindow() : QMainWindow()
init_images();
homedir = getHomeDir();
#ifdef MDEBUG
CRYPTO_malloc_debug_init();
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
qWarning() << "malloc() debugging on.";
#endif
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
@ -431,10 +424,7 @@ MainWindow::~MainWindow()
OBJ_cleanup();
delete dbindex;
delete helpdlg;
#ifdef MDEBUG
fprintf(stderr, "Memdebug:\n");
CRYPTO_mem_leaks_fp(stderr);
#endif
XcaProgress::setGui(nullptr);
}